diff options
522 files changed, 11090 insertions, 4682 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index e3a53d76eac..53bcdd95eeb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,9 +49,9 @@ ENDIF() SET(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel") -# MAX_INDEXES - Set the maximum number of indexes per table, default 64U +# MAX_INDEXES - Set the maximum number of indexes per table, default 64 IF (NOT MAX_INDEXES) - SET(MAX_INDEXES 64U) + SET(MAX_INDEXES 64) ENDIF(NOT MAX_INDEXES) IF (${MAX_INDEXES} GREATER 128) @@ -3,8 +3,9 @@ organization registered in the USA. The current main sponsors of the MariaDB Foundation are: -Alibaba Cloud https://intl.aliyun.com (2017) +Alibaba Cloud https://www.alibabacloud.com/ (2017) Booking.com https://www.booking.com (2013) +Microsoft https://microsoft.com/ (2017) Tencent Cloud https://cloud.tencent.com (2017) Development Bank of Singapore https://dbs.com (2016) IBM https://www.ibm.com (2017) diff --git a/appveyor.yml b/appveyor.yml index a005fc5a93f..c17c0c3bb77 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,17 +1,21 @@ -version: 10.2-{build} +version: build-{build}~branch-{branch} + before_build: -- md %APPVEYOR_BUILD_FOLDER%\win_build -- cd %APPVEYOR_BUILD_FOLDER%\win_build -- cmake .. -G "Visual Studio 15 2017" -DBISON_EXECUTABLE=C:\cygwin\bin\bison -- dir + - md %APPVEYOR_BUILD_FOLDER%\win_build + - cd %APPVEYOR_BUILD_FOLDER%\win_build + - cmake .. -G "Visual Studio 15 2017 Win64" -DWITH_UNIT_TESTS=0 -DBISON_EXECUTABLE=C:\cygwin\bin\bison + build: project: win_build\MySQL.sln parallel: true verbosity: minimal -configuration: - - Debug -test: + +configuration: RelWithDebInfo +platform: x64 + test_script: -- cd %APPVEYOR_BUILD_FOLDER%\win_build\mysql-test -- perl mysql-test-run.pl --force --max-test-fail=20 --parallel=6 --testcase-timeout=4 --skip-test-list=unstable-tests --suite=main,innodb,plugins,mariabackup + - set PATH=%PATH%;C:\Program Files (x86)\Windows Kits\10\Debuggers\x64 + - cd %APPVEYOR_BUILD_FOLDER%\win_build\mysql-test + - perl mysql-test-run.pl --force --max-test-fail=10 --parallel=auto --testcase-timeout=10 --skip-test-list=unstable-tests --suite=main,innodb,plugins,mariabackup + image: Visual Studio 2017 diff --git a/client/mysql.cc b/client/mysql.cc index 929fba73ab5..81406df36c2 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -1140,6 +1140,7 @@ int main(int argc,char *argv[]) current_prompt = my_strdup(default_prompt,MYF(MY_WME)); prompt_counter=0; aborted= 0; + sf_leaking_memory= 1; /* no memory leak reports yet */ outfile[0]=0; // no (default) outfile strmov(pager, "stdout"); // the default, if --pager wasn't given @@ -1205,6 +1206,7 @@ int main(int argc,char *argv[]) my_end(0); exit(1); } + sf_leaking_memory= 0; glob_buffer.realloc(512); completion_hash_init(&ht, 128); init_alloc_root(&hash_mem_root, "hash", 16384, 0, MYF(0)); @@ -1799,10 +1801,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), #ifndef EMBEDDED_LIBRARY if ((opt_protocol= find_type_with_warning(argument, &sql_protocol_typelib, opt->name)) <= 0) - { - sf_leaking_memory= 1; /* no memory leak reports here */ exit(1); - } #endif break; case OPT_SERVER_ARG: @@ -4597,8 +4596,11 @@ static char *get_arg(char *line, get_arg_mode mode) } for (start=ptr ; *ptr; ptr++) { - if ((*ptr == '\\' && ptr[1]) || // escaped character - (!short_cmd && qtype && *ptr == qtype && ptr[1] == qtype)) // quote + /* if short_cmd use historical rules (only backslash) otherwise SQL rules */ + if (short_cmd + ? (*ptr == '\\' && ptr[1]) // escaped character + : (*ptr == '\\' && ptr[1] && qtype != '`') || // escaped character + (qtype && *ptr == qtype && ptr[1] == qtype)) // quote { // Remove (or skip) the backslash (or a second quote) if (mode != CHECK) diff --git a/client/mysqltest.cc b/client/mysqltest.cc index da959f48652..cdfd6657a56 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -1568,7 +1568,6 @@ static void cleanup_and_exit(int exit_code) } } - sf_leaking_memory= 0; /* all memory should be freed by now */ exit(exit_code); } @@ -7296,10 +7295,7 @@ get_one_option(int optid, const struct my_option *opt, char *argument) #ifndef EMBEDDED_LIBRARY if ((opt_protocol= find_type_with_warning(argument, &sql_protocol_typelib, opt->name)) <= 0) - { - sf_leaking_memory= 1; /* no memory leak reports here */ exit(1); - } #endif break; case '?': diff --git a/cmake/build_configurations/mysql_release.cmake b/cmake/build_configurations/mysql_release.cmake index 8221029a2d6..c3c42efa7a0 100644 --- a/cmake/build_configurations/mysql_release.cmake +++ b/cmake/build_configurations/mysql_release.cmake @@ -1,4 +1,5 @@ # Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2018, MariaDB Corporation # # 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 diff --git a/cmake/check_compiler_flag.cmake b/cmake/check_compiler_flag.cmake index 6b29ac5ab6b..ab5a15f8457 100644 --- a/cmake/check_compiler_flag.cmake +++ b/cmake/check_compiler_flag.cmake @@ -32,25 +32,25 @@ MACRO (MY_CHECK_CXX_COMPILER_FLAG flag) SET(CMAKE_REQUIRED_FLAGS "${SAVE_CMAKE_REQUIRED_FLAGS}") ENDMACRO() -FUNCTION(MY_CHECK_AND_SET_COMPILER_FLAG flag) +FUNCTION(MY_CHECK_AND_SET_COMPILER_FLAG flag_to_set) # At the moment this is gcc-only. # Let's avoid expensive compiler tests on Windows: IF(WIN32) RETURN() ENDIF() - MY_CHECK_C_COMPILER_FLAG(${flag}) - MY_CHECK_CXX_COMPILER_FLAG(${flag}) - STRING(REGEX REPLACE "[-,= +]" "_" result "${flag}") + STRING(REGEX REPLACE "^-Wno-" "-W" flag_to_check ${flag_to_set}) + MY_CHECK_C_COMPILER_FLAG(${flag_to_check}) + MY_CHECK_CXX_COMPILER_FLAG(${flag_to_check}) + STRING(REGEX REPLACE "[-,= +]" "_" result "${flag_to_check}") FOREACH(lang C CXX) IF (have_${lang}_${result}) IF(ARGN) FOREACH(type ${ARGN}) - SET(CMAKE_${lang}_FLAGS_${type} "${CMAKE_${lang}_FLAGS_${type}} ${flag}" PARENT_SCOPE) + SET(CMAKE_${lang}_FLAGS_${type} "${CMAKE_${lang}_FLAGS_${type}} ${flag_to_set}" PARENT_SCOPE) ENDFOREACH() ELSE() - SET(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} ${flag}" PARENT_SCOPE) + SET(CMAKE_${lang}_FLAGS "${CMAKE_${lang}_FLAGS} ${flag_to_set}" PARENT_SCOPE) ENDIF() ENDIF() ENDFOREACH() ENDFUNCTION() - diff --git a/cmake/maintainer.cmake b/cmake/maintainer.cmake index 77f55837fdb..6993bae3975 100644 --- a/cmake/maintainer.cmake +++ b/cmake/maintainer.cmake @@ -14,54 +14,33 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA # Common warning flags for GCC, G++, Clang and Clang++ -SET(MY_WARNING_FLAGS "-Wall -Wextra -Wformat-security -Wno-init-self") -MY_CHECK_C_COMPILER_FLAG("-Wvla") # Requires GCC 4.3+ or Clang -IF(have_C__Wvla) - SET(MY_WARNING_FLAGS "${MY_WARNING_FLAGS} -Wvla") -ENDIF() - -MY_CHECK_C_COMPILER_FLAG("-Wno-format-truncation") -IF(HAVE_C__Wno_format_truncation) - SET(MY_WARNING_FLAGS "${MY_WARNING_FLAGS} -Wno-format-truncation") -ENDIF() - -# Common warning flags for GCC and Clang -SET(MY_C_WARNING_FLAGS - "${MY_WARNING_FLAGS} -Wwrite-strings -Wdeclaration-after-statement") - -# Common warning flags for G++ and Clang++ -SET(MY_CXX_WARNING_FLAGS - "${MY_WARNING_FLAGS} -Woverloaded-virtual -Wno-unused-parameter") - -# Extra warning flags for Clang++ -IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang") - SET(MY_CXX_WARNING_FLAGS - "${MY_CXX_WARNING_FLAGS} -Wno-null-conversion -Wno-unused-private-field") -ENDIF() - -# Turn on Werror (warning => error) when using maintainer mode. -IF(MYSQL_MAINTAINER_MODE MATCHES "ERR") - SET(MY_C_WARNING_FLAGS "${MY_C_WARNING_FLAGS} -DFORCE_INIT_OF_VARS -Werror") - SET(MY_CXX_WARNING_FLAGS "${MY_CXX_WARNING_FLAGS} -DFORCE_INIT_OF_VARS -Werror") -ENDIF() - -# Set warning flags for GCC/Clang -IF(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") - SET(MY_MAINTAINER_C_WARNINGS "${MY_C_WARNING_FLAGS}") -ENDIF() -# Set warning flags for G++/Clang++ -IF(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang") - SET(MY_MAINTAINER_CXX_WARNINGS "${MY_CXX_WARNING_FLAGS} -Wnon-virtual-dtor") -ENDIF() +SET(MY_WARNING_FLAGS + -Wall + -Wdeclaration-after-statement + -Wextra + -Wformat-security + -Wno-format-truncation + -Wno-init-self + -Wno-nonnull-compare + -Wno-null-conversion + -Wno-unused-parameter + -Wno-unused-private-field + -Woverloaded-virtual + -Wnon-virtual-dtor + -Wvla + -Wwrite-strings + ) IF(MYSQL_MAINTAINER_MODE MATCHES "ON") - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${MY_MAINTAINER_C_WARNINGS}") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MY_MAINTAINER_CXX_WARNINGS}") + SET(WHERE) ELSEIF(MYSQL_MAINTAINER_MODE MATCHES "AUTO") - SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${MY_MAINTAINER_C_WARNINGS}") - SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${MY_MAINTAINER_CXX_WARNINGS}") + SET(WHERE DEBUG) ENDIF() +FOREACH(F ${MY_WARNING_FLAGS}) + MY_CHECK_AND_SET_COMPILER_FLAG(${F} ${WHERE}) +ENDFOREACH() + IF(CMAKE_C_COMPILER_ID MATCHES "GNU") STRING(REPLACE " -E " " -E -dDI " CMAKE_C_CREATE_PREPROCESSED_SOURCE ${CMAKE_C_CREATE_PREPROCESSED_SOURCE}) ENDIF() diff --git a/config.h.cmake b/config.h.cmake index 31a563037a0..f53b177573d 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -131,6 +131,7 @@ #cmakedefine HAVE_CLOCK_GETTIME 1 #cmakedefine HAVE_CRYPT 1 #cmakedefine HAVE_CUSERID 1 +#cmakedefine HAVE_DLADDR 1 #cmakedefine HAVE_DLERROR 1 #cmakedefine HAVE_DLOPEN 1 #cmakedefine HAVE_FCHMOD 1 diff --git a/configure.cmake b/configure.cmake index 40aca55dc47..464543502dc 100644 --- a/configure.cmake +++ b/configure.cmake @@ -329,6 +329,7 @@ CHECK_FUNCTION_EXISTS (cuserid HAVE_CUSERID) CHECK_FUNCTION_EXISTS (ftruncate HAVE_FTRUNCATE) CHECK_FUNCTION_EXISTS (compress HAVE_COMPRESS) CHECK_FUNCTION_EXISTS (crypt HAVE_CRYPT) +CHECK_FUNCTION_EXISTS (dladdr HAVE_DLADDR) CHECK_FUNCTION_EXISTS (dlerror HAVE_DLERROR) CHECK_FUNCTION_EXISTS (dlopen HAVE_DLOPEN) CHECK_FUNCTION_EXISTS (fchmod HAVE_FCHMOD) @@ -379,7 +380,6 @@ CHECK_FUNCTION_EXISTS (pthread_rwlock_rdlock HAVE_PTHREAD_RWLOCK_RDLOCK) CHECK_FUNCTION_EXISTS (pthread_sigmask HAVE_PTHREAD_SIGMASK) CHECK_FUNCTION_EXISTS (pthread_yield_np HAVE_PTHREAD_YIELD_NP) CHECK_FUNCTION_EXISTS (putenv HAVE_PUTENV) -CHECK_FUNCTION_EXISTS (readdir_r HAVE_READDIR_R) CHECK_FUNCTION_EXISTS (readlink HAVE_READLINK) CHECK_FUNCTION_EXISTS (realpath HAVE_REALPATH) CHECK_FUNCTION_EXISTS (rename HAVE_RENAME) @@ -416,6 +416,16 @@ IF(HAVE_SYS_EVENT_H) CHECK_FUNCTION_EXISTS (kqueue HAVE_KQUEUE) ENDIF() +# readdir_r might exist, but be marked deprecated +SET(CMAKE_REQUIRED_FLAGS -Werror) +CHECK_CXX_SOURCE_COMPILES( +"#include <dirent.h> +int main() { + readdir_r(0,0,0); + return 0; + }" HAVE_READDIR_R) +SET(CMAKE_REQUIRED_FLAGS) + #-------------------------------------------------------------------- # Support for WL#2373 (Use cycle counter for timing) #-------------------------------------------------------------------- diff --git a/debian/additions/debian-start.inc.sh b/debian/additions/debian-start.inc.sh index cfe51936613..0640bf9c2a6 100755 --- a/debian/additions/debian-start.inc.sh +++ b/debian/additions/debian-start.inc.sh @@ -72,7 +72,7 @@ function check_root_accounts() { logger -p daemon.info -i -t$0 "Checking for insecure root accounts." - ret=$( echo "SELECT count(*) FROM mysql.user WHERE user='root' and password='';" | $MYSQL --skip-column-names ) + ret=$( echo "SELECT count(*) FROM mysql.user WHERE user='root' and password='' and plugin in ('', 'mysql_native_password', 'mysql_old_password');" | $MYSQL --skip-column-names ) if [ "$ret" -ne "0" ]; then logger -p daemon.warn -i -t$0 "WARNING: mysql.user contains $ret root accounts without password!" fi diff --git a/extra/mariabackup/xtrabackup.cc b/extra/mariabackup/xtrabackup.cc index 338706b3113..2d2734e0f30 100644 --- a/extra/mariabackup/xtrabackup.cc +++ b/extra/mariabackup/xtrabackup.cc @@ -1264,10 +1264,10 @@ end: static const char *xb_client_default_groups[]= - { "xtrabackup", "client", 0, 0, 0 }; + { "xtrabackup", "mariabackup", "client", 0, 0, 0 }; static const char *xb_server_default_groups[]= - { "xtrabackup", "mysqld", 0, 0, 0 }; + { "xtrabackup", "mariabackup", "mysqld", 0, 0, 0 }; static void print_version(void) { @@ -1294,7 +1294,7 @@ GNU General Public License for more details.\n\ \n\ You can download full text of the license on http://www.gnu.org/licenses/gpl-2.0.txt\n"); - printf("Usage: [%s [--defaults-file=#] --backup | %s [--defaults-file=#] --prepare] [OPTIONS]\n",my_progname,my_progname); + printf("Usage: %s [--defaults-file=#] [--backup | --prepare | --copy-back | --move-back] [OPTIONS]\n",my_progname); print_defaults("my", xb_server_default_groups); my_print_help(xb_client_options); my_print_help(xb_server_options); @@ -4970,9 +4970,19 @@ xb_init() return(false); } - if (opt_rsync && xtrabackup_stream_fmt) { - msg("Error: --rsync doesn't work with --stream\n"); - return(false); + if (xtrabackup_backup && opt_rsync) + { + if (xtrabackup_stream_fmt) + { + msg("Error: --rsync doesn't work with --stream\n"); + return(false); + } + bool have_rsync = IF_WIN(false, (system("rsync --version > /dev/null 2>&1") == 0)); + if (!have_rsync) + { + msg("Error: rsync executable not found, cannot run backup with --rsync\n"); + return false; + } } n_mixed_options = 0; diff --git a/include/ma_dyncol.h b/include/ma_dyncol.h index 300474e061e..4f05b425afd 100644 --- a/include/ma_dyncol.h +++ b/include/ma_dyncol.h @@ -69,6 +69,9 @@ typedef struct st_mysql_lex_string LEX_STRING; #define DYNCOL_UTF (&my_charset_utf8_general_ci) #endif +/* escape json strings */ +#define DYNCOL_JSON_ESC ((char)1) + enum enum_dyncol_func_result { ER_DYNCOL_OK= 0, diff --git a/include/my_compare.h b/include/my_compare.h index 12f9971d49b..f4e9ecbf80b 100644 --- a/include/my_compare.h +++ b/include/my_compare.h @@ -91,17 +91,19 @@ typedef struct st_HA_KEYSEG /* Key-portion */ #define size_to_store_key_length(length) ((length) < 255 ? 1 : 3) -#define get_rec_bits(bit_ptr, bit_ofs, bit_len) \ - (((((uint16) (bit_ptr)[1] << 8) | (uint16) (bit_ptr)[0]) >> (bit_ofs)) & \ - ((1 << (bit_len)) - 1)) - -#define set_rec_bits(bits, bit_ptr, bit_ofs, bit_len) \ -{ \ - (bit_ptr)[0]= ((bit_ptr)[0] & ~(((1 << (bit_len)) - 1) << (bit_ofs))) | \ - ((bits) << (bit_ofs)); \ - if ((bit_ofs) + (bit_len) > 8) \ - (bit_ptr)[1]= ((bit_ptr)[1] & ~((1 << ((bit_len) - 8 + (bit_ofs))) - 1)) | \ - ((bits) >> (8 - (bit_ofs))); \ +static inline uchar get_rec_bits(const uchar *ptr, uchar ofs, uint len) +{ + uint16 val= ptr[0]; + if (ofs + len > 8) + val|= (uint16)(ptr[1]) << 8; + return (val >> ofs) & ((1 << len) - 1); +} + +static inline void set_rec_bits(uint16 bits, uchar *ptr, uchar ofs, uint len) +{ + ptr[0]= (ptr[0] & ~(((1 << len) - 1) << ofs)) | (bits << ofs); + if (ofs + len > 8) + ptr[1]= (ptr[1] & ~((1 << (len - 8 + ofs)) - 1)) | (bits >> (8 - ofs)); } #define clr_rec_bits(bit_ptr, bit_ofs, bit_len) \ diff --git a/include/my_global.h b/include/my_global.h index cb31ae233bd..5c325b76a7b 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -1091,11 +1091,19 @@ static inline char *dlerror(void) #ifndef HAVE_DLERROR #define dlerror() "" #endif +#ifndef HAVE_DLADDR +#define dladdr(A, B) 0 +/* Dummy definition in case we're missing dladdr() */ +typedef struct { const char *dli_fname, dli_fbase; } Dl_info; +#endif #else #define dlerror() "No support for dynamic loading (static build?)" #define dlopen(A,B) 0 #define dlsym(A,B) 0 #define dlclose(A) 0 +#define dladdr(A, B) 0 +/* Dummy definition in case we're missing dladdr() */ +typedef struct { const char *dli_fname, dli_fbase; } Dl_info; #endif /* diff --git a/include/my_valgrind.h b/include/my_valgrind.h index dd95098cc44..c585e3c489a 100644 --- a/include/my_valgrind.h +++ b/include/my_valgrind.h @@ -13,6 +13,14 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA */ +/* clang -> gcc */ +#ifndef __has_feature +# define __has_feature(x) 0 +#endif +#if __has_feature(address_sanitizer) +# define __SANITIZE_ADDRESS__ 1 +#endif + #ifdef HAVE_valgrind #define IF_VALGRIND(A,B) A #else @@ -25,7 +33,13 @@ # define MEM_NOACCESS(a,len) VALGRIND_MAKE_MEM_NOACCESS(a,len) # define MEM_CHECK_ADDRESSABLE(a,len) VALGRIND_CHECK_MEM_IS_ADDRESSABLE(a,len) # define MEM_CHECK_DEFINED(a,len) VALGRIND_CHECK_MEM_IS_DEFINED(a,len) -#else /* HAVE_VALGRIND_MEMCHECK_H */ +#elif defined(__SANITIZE_ADDRESS__) +# include <sanitizer/asan_interface.h> +# define MEM_UNDEFINED(a,len) ASAN_UNPOISON_MEMORY_REGION(a,len) +# define MEM_NOACCESS(a,len) ASAN_POISON_MEMORY_REGION(a,len) +# define MEM_CHECK_ADDRESSABLE(a,len) ((void) 0) +# define MEM_CHECK_DEFINED(a,len) ((void) 0) +#else # define MEM_UNDEFINED(a,len) ((void) 0) # define MEM_NOACCESS(a,len) ((void) 0) # define MEM_CHECK_ADDRESSABLE(a,len) ((void) 0) @@ -33,13 +47,10 @@ #endif /* HAVE_VALGRIND_MEMCHECK_H */ #if !defined(DBUG_OFF) || defined(TRASH_FREED_MEMORY) -#define TRASH_FILL(A,B,C) do { const size_t trash_tmp= (B); memset(A, C, trash_tmp); MEM_UNDEFINED(A, trash_tmp); } while (0) +#define TRASH_FILL(A,B,C) do { const size_t trash_tmp= (B); MEM_UNDEFINED(A, trash_tmp); memset(A, C, trash_tmp); } while (0) #else -#define TRASH_FILL(A,B,C) do{ const size_t trash_tmp __attribute__((unused)) = (B) ; MEM_CHECK_ADDRESSABLE(A,trash_tmp);MEM_UNDEFINED(A,trash_tmp);} while (0) +#define TRASH_FILL(A,B,C) do { const size_t trash_tmp __attribute__((unused))= (B); MEM_UNDEFINED(A,trash_tmp); } while (0) #endif -#define TRASH_ALLOC(A,B) TRASH_FILL(A,B,0xA5) -#define TRASH_FREE(A,B) TRASH_FILL(A,(size_t) (B),0x8F) -#define TRASH(A,B) TRASH_FREE(A,B) -# define DBUG_ASSERT_DEFINED(x) \ - DBUG_ASSERT(!VALGRIND_CHECK_MEM_IS_DEFINED(&(x), sizeof(x))) +#define TRASH_ALLOC(A,B) do { TRASH_FILL(A,B,0xA5); MEM_UNDEFINED(A,B); } while(0) +#define TRASH_FREE(A,B) do { TRASH_FILL(A,B,0x8F); MEM_NOACCESS(A,B); } while(0) diff --git a/include/ssl_compat.h b/include/ssl_compat.h index 568af6e1db4..54e80af769d 100644 --- a/include/ssl_compat.h +++ b/include/ssl_compat.h @@ -51,14 +51,6 @@ #define HAVE_OPENSSL10 1 #define SSL_LIBRARY SSLeay_version(SSLEAY_VERSION) -/* - Unfortunately RAND_bytes manual page does not provide any guarantees - in relation to blocking behavior. Here we explicitly use SSLeay random - instead of whatever random engine is currently set in OpenSSL. That way - we are guaranteed to have a non-blocking random. -*/ -#define RAND_OpenSSL() RAND_SSLeay() - #ifdef HAVE_ERR_remove_thread_state #define ERR_remove_state(X) ERR_remove_thread_state(NULL) #endif /* HAVE_ERR_remove_thread_state */ diff --git a/include/welcome_copyright_notice.h b/include/welcome_copyright_notice.h index cd7cd6692be..1b4b17cfc0d 100644 --- a/include/welcome_copyright_notice.h +++ b/include/welcome_copyright_notice.h @@ -17,7 +17,7 @@ #ifndef _welcome_copyright_notice_h_ #define _welcome_copyright_notice_h_ -#define COPYRIGHT_NOTICE_CURRENT_YEAR "2017" +#define COPYRIGHT_NOTICE_CURRENT_YEAR "2018" /* This define specifies copyright notice which is displayed by every MySQL diff --git a/libmariadb b/libmariadb -Subproject cfafbb6babf276a4f78db626d192c6d844a9b4d +Subproject 058fc080b4ee95bce405c182ae8d542576863f8 diff --git a/mysql-test/CMakeLists.txt b/mysql-test/CMakeLists.txt index 7e5ef3fb8df..a93eb4a5084 100644 --- a/mysql-test/CMakeLists.txt +++ b/mysql-test/CMakeLists.txt @@ -1,4 +1,5 @@ # Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2018, MariaDB Corporation # # 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 diff --git a/mysql-test/collections/buildbot_suites.bat b/mysql-test/collections/buildbot_suites.bat index 89e68919c7f..40b1aceca10 100644 --- a/mysql-test/collections/buildbot_suites.bat +++ b/mysql-test/collections/buildbot_suites.bat @@ -1,6 +1,8 @@ -perl mysql-test-run.pl --verbose-restart --force --testcase-timeout=45 --suite-timeout=600 --max-test-fail=500 --retry=3 --parallel=4 --suite=^ +perl mysql-test-run.pl --verbose-restart --force --suite-timeout=120 --max-test-fail=10 --retry=3 --parallel=4 --suite=^ main,^ innodb,^ plugins,^ mariabackup,^ +roles,^ +auth_gssapi,^ rocksdb diff --git a/mysql-test/include/assert_grep.inc b/mysql-test/include/assert_grep.inc index a980a6d73b1..9f2c8505262 100644 --- a/mysql-test/include/assert_grep.inc +++ b/mysql-test/include/assert_grep.inc @@ -130,7 +130,10 @@ EOF --let $_ag_outcome= `SELECT LOAD_FILE('$_AG_OUT')` if ($_ag_outcome != 'assert_grep.inc ok') { - --source include/show_rpl_debug_info.inc + if ($rpl_server_count != '') + { + --source include/show_rpl_debug_info.inc + } --echo include/assert_grep.inc failed! --echo assert_text: '$assert_text' --echo assert_file: '$assert_file' diff --git a/mysql-test/lib/My/SafeProcess.pm b/mysql-test/lib/My/SafeProcess.pm index 3260a6ed593..0387d09b89c 100644 --- a/mysql-test/lib/My/SafeProcess.pm +++ b/mysql-test/lib/My/SafeProcess.pm @@ -84,7 +84,7 @@ sub is_child { } -my @safe_process_cmd; +our @safe_process_cmd; my $safe_kill; my $bindir; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index c5ff0c4f52f..bfb50fe34d3 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -1586,6 +1586,7 @@ sub command_line_setup { $opt_manual_debug || $opt_dbx || $opt_client_dbx || $opt_manual_dbx || $opt_debugger || $opt_client_debugger ) { + $ENV{ASAN_OPTIONS}= 'abort_on_error=1:'.($ENV{ASAN_OPTIONS} || ''); if ( using_extern() ) { mtr_error("Can't use --extern when using debugger"); @@ -3185,6 +3186,9 @@ sub mysql_install_db { mtr_appendfile_to_file("$sql_dir/mysql_performance_tables.sql", $bootstrap_sql_file); + # Don't install anonymous users + mtr_tofile($bootstrap_sql_file, "set \@skip_auth_anonymous=1;\n"); + # Add the mysql system tables initial data # for a production system mtr_appendfile_to_file("$sql_dir/mysql_system_tables_data.sql", @@ -3219,10 +3223,6 @@ sub mysql_install_db { sql_to_bootstrap($text)); } - # Remove anonymous users - mtr_tofile($bootstrap_sql_file, - "DELETE FROM mysql.user where user= '';\n"); - # Create mtr database mtr_tofile($bootstrap_sql_file, "CREATE DATABASE mtr CHARSET=latin1;\n"); @@ -5030,7 +5030,7 @@ sub mysqld_start ($$) { my $args; mtr_init_args(\$args); - if ( $opt_valgrind_mysqld ) + if ( $opt_valgrind_mysqld and not $opt_gdb and not $opt_manual_gdb ) { valgrind_arguments($args, \$exe); } @@ -5618,11 +5618,20 @@ sub gdb_arguments { unlink($gdb_init_file); # Put $args into a single string - my $str= join(" ", @$$args); $input = $input ? "< $input" : ""; - # write init file for mysqld or client - mtr_tofile($gdb_init_file, "set args $str $input\n"); + if ($type ne 'client' and $opt_valgrind_mysqld) { + my $v = $$exe; + my $vargs = []; + valgrind_arguments($vargs, \$v); + mtr_tofile($gdb_init_file, <<EOF); +shell @My::SafeProcess::safe_process_cmd --parent-pid=`pgrep -x gdb` -- $v --vgdb-error=0 @$vargs @$$args & +shell sleep 1 +target remote | /usr/lib64/valgrind/../../bin/vgdb +EOF + } else { + mtr_tofile($gdb_init_file, "set args @$$args $input\n"); + } if ( $opt_manual_gdb ) { diff --git a/mysql-test/r/contributors.result b/mysql-test/r/contributors.result index 5d92184f191..927c0bcccbf 100644 --- a/mysql-test/r/contributors.result +++ b/mysql-test/r/contributors.result @@ -1,8 +1,9 @@ SHOW CONTRIBUTORS; Name Location Comment Booking.com https://www.booking.com Founding member, Platinum Sponsor of the MariaDB Foundation -Alibaba Cloud https://intl.aliyun.com Platinum Sponsor of the MariaDB Foundation +Alibaba Cloud https://www.alibabacloud.com/ Platinum Sponsor of the MariaDB Foundation Tencent Cloud https://cloud.tencent.com Platinum Sponsor of the MariaDB Foundation +Microsoft https://microsoft.com/ Platinum Sponsor of the MariaDB Foundation MariaDB Corporation https://mariadb.com Founding member, Gold Sponsor of the MariaDB Foundation Visma https://visma.com Gold Sponsor of the MariaDB Foundation DBS https://dbs.com Gold Sponsor of the MariaDB Foundation diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index b4636dca7e2..dc34185ad2e 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -1948,6 +1948,144 @@ drop function f1; create table t1(ID decimal(2,1) unsigned NOT NULL, PRIMARY KEY (ID))engine=memory select 2.1 ID; drop table t1; +create table t1 ( +f01 int, f02 int, f03 int, f04 int, f05 int, f06 int, f07 int, f08 int, f09 int, f10 int, f11 int, f12 int, f13 int, f14 int, f15 int, f16 int, f17 int, f18 int, f19 int, f20 int, f21 int, f22 int, f23 int, f24 int, f25 int, f26 int, f27 int, f28 int, f29 int, f30 int, f31 int, f32 int, f33 int, f34 int, f35 int, f36 int, f37 int, f38 int, f39 int, f40 int, f41 int, f42 int, f43 int, f44 int, f45 int, f46 int, f47 int, f48 int, f49 int, f50 int, f51 int, f52 int, f53 int, f54 int, f55 int, f56 int, f57 int, f58 int, f59 int, f60 int, f61 int, f62 int, f63 int, f64 int, +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0001 (f01) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0002 (f02) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0003 (f03) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0004 (f04) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0005 (f05) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0006 (f06) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0007 (f07) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0008 (f08) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0009 (f09) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0010 (f10) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0011 (f11) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0012 (f12) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0013 (f13) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0014 (f14) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0015 (f15) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0016 (f16) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0017 (f17) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0018 (f18) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0019 (f19) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0020 (f20) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0021 (f21) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0022 (f22) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0023 (f23) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0024 (f24) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0025 (f25) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0026 (f26) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0027 (f27) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0028 (f28) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0029 (f29) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0030 (f30) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0031 (f31) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0032 (f32) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0033 (f33) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0034 (f34) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0035 (f35) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0036 (f36) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0037 (f37) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0038 (f38) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0039 (f39) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0040 (f40) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0041 (f41) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0042 (f42) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0043 (f43) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0044 (f44) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0045 (f45) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0046 (f46) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0047 (f47) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0048 (f48) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0049 (f49) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0050 (f50) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0051 (f51) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0052 (f52) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0053 (f53) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0054 (f54) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0055 (f55) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0056 (f56) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0057 (f57) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0058 (f58) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0059 (f59) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0060 (f60) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0061 (f61) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0062 (f62) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0063 (f63) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0064 (f64) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +fend int); +ERROR HY000: Cannot create table `t1`: index information is too long. Decrease number of indexes or use shorter index names or shorter comments. +create table t1 ( +f01 int, f02 int, f03 int, f04 int, f05 int, f06 int, f07 int, f08 int, f09 int, f10 int, f11 int, f12 int, f13 int, f14 int, f15 int, f16 int, f17 int, f18 int, f19 int, f20 int, f21 int, f22 int, f23 int, f24 int, f25 int, f26 int, f27 int, f28 int, f29 int, f30 int, f31 int, f32 int, f33 int, f34 int, f35 int, f36 int, f37 int, f38 int, f39 int, f40 int, f41 int, f42 int, f43 int, f44 int, f45 int, f46 int, f47 int, f48 int, f49 int, f50 int, f51 int, f52 int, f53 int, f54 int, f55 int, f56 int, f57 int, f58 int, f59 int, f60 int, f61 int, f62 int, f63 int, f64 int, +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0001 (f01) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0002 (f02) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0003 (f03) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0004 (f04) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0005 (f05) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0006 (f06) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0007 (f07) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0008 (f08) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0009 (f09) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0010 (f10) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0011 (f11) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0012 (f12) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0013 (f13) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0014 (f14) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0015 (f15) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0016 (f16) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0017 (f17) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0018 (f18) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0019 (f19) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0020 (f20) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0021 (f21) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0022 (f22) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0023 (f23) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0024 (f24) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0025 (f25) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0026 (f26) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0027 (f27) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0028 (f28) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0029 (f29) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0030 (f30) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0031 (f31) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0032 (f32) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0033 (f33) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0034 (f34) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0035 (f35) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0036 (f36) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0037 (f37) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0038 (f38) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0039 (f39) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0040 (f40) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0041 (f41) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0042 (f42) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0043 (f43) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0044 (f44) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0045 (f45) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0046 (f46) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0047 (f47) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0048 (f48) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0049 (f49) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0050 (f50) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0051 (f51) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0052 (f52) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0053 (f53) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0054 (f54) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0055 (f55) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0056 (f56) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0057 (f57) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0058 (f58) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0059 (f59) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0060 (f60) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0061 (f61) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0062 (f62) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0063 (f63) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', +fend int); +alter table t1 add +key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0064 (f64) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'; +ERROR HY000: Cannot create table `t1`: index information is too long. Decrease number of indexes or use shorter index names or shorter comments. +drop table t1; End of 5.5 tests create table t1; ERROR 42000: A table must have at least 1 column diff --git a/mysql-test/r/cte_nonrecursive.result b/mysql-test/r/cte_nonrecursive.result index b1fd287f1d7..738135215c2 100644 --- a/mysql-test/r/cte_nonrecursive.result +++ b/mysql-test/r/cte_nonrecursive.result @@ -1369,3 +1369,32 @@ n_nationkey n_name n_regionkey r_regionkey r_name 23 UNITED KINGDOM 3 3 EUROPE drop view v; drop table region, nation; +# +# MDEV-15120: cte name used with database name +# +WITH cte AS (SELECT 1 AS a) SELECT test.cte.a FROM test.cte; +ERROR 42S02: Table 'test.cte' doesn't exist +CREATE DATABASE db1; +USE db1; +WITH cte AS (SELECT 1 AS a) SELECT db1.cte.a FROM db1.cte; +ERROR 42S02: Table 'db1.cte' doesn't exist +DROP DATABASE db1; +USE test; +# +# MDEV-15119: CTE c2 specified after CTE c1 and is used in +# CTE c3 that is embedded into the spec of c1 +# +CREATE TABLE t1 (i int); +INSERT INTO t1 VALUES (1),(2),(3); +WITH c1 AS (WITH c3 AS (SELECT * FROM c2) SELECT * FROM c3), +c2 AS (SELECT * FROM t1) +SELECT * FROM c1; +ERROR 42S02: Table 'test.c2' doesn't exist +WITH RECURSIVE c1 AS (WITH c3 AS (SELECT * FROM c2) SELECT * FROM c3), +c2 AS (SELECT * FROM t1) +SELECT * FROM c1; +i +1 +2 +3 +DROP TABLE t1; diff --git a/mysql-test/r/cte_recursive.result b/mysql-test/r/cte_recursive.result index d87802f57f3..2a454ecdcd2 100644 --- a/mysql-test/r/cte_recursive.result +++ b/mysql-test/r/cte_recursive.result @@ -3057,6 +3057,19 @@ Note 1003 with recursive destinations as (/* select#2 */ select `test`.`a`.`arri set standard_compliant_cte=default; drop table flights; # +# MDEV-15162: Setting user variable in recursive CTE +# +SET @c=1; +WITH RECURSIVE cte AS +(SELECT 5 +UNION +SELECT @c:=@c+1 FROM cte WHERE @c<3) +SELECT * FROM cte; +5 +5 +2 +3 +# # MDEV-14217 [db crash] Recursive CTE when SELECT includes new field # CREATE TEMPORARY TABLE a_tbl ( diff --git a/mysql-test/r/derived.result b/mysql-test/r/derived.result index 220fd5a8c74..d227bbd7f06 100644 --- a/mysql-test/r/derived.result +++ b/mysql-test/r/derived.result @@ -1041,6 +1041,47 @@ id id data 2 2 yes 1 NULL NULL drop table t1; +# +# MDEV-14241: Server crash in key_copy / get_matching_chain_by_join_key +# or valgrind warnings +# +CREATE TABLE t1 (a VARCHAR(10)) ENGINE=MyISAM; +CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES ('foo'),('bar'); +CREATE TABLE t2 (b integer auto_increment primary key) ENGINE=MyISAM; +INSERT INTO t2 VALUES (NULL),(NULL); +CREATE TABLE t3 (c VARCHAR(1024) CHARACTER SET utf8, d INT) ENGINE=MyISAM; +CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v3 AS SELECT * FROM t3; +INSERT INTO t3 VALUES ('abc',NULL),('def',4); +SET join_cache_level= 8; +explain +SELECT * FROM v1, t2, v3 WHERE a = c AND b = d; +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY <derived2> ALL NULL NULL NULL NULL 2 +1 PRIMARY <derived3> hash_ALL NULL #hash#$hj 3075 func 2 Using where; Using join buffer (flat, BNLH join) +1 PRIMARY t2 eq_ref PRIMARY PRIMARY 4 v3.d 1 Using index +3 DERIVED t3 ALL NULL NULL NULL NULL 2 +2 DERIVED t1 ALL NULL NULL NULL NULL 2 +SELECT * FROM v1, t2, v3 WHERE a = c AND b = d; +a b c d +DROP VIEW v1, v3; +DROP TABLE t1, t2, t3; +# +# MDEV-14786: Server crashes in Item_cond::transform on 2nd +# execution of SP querying from a view +# +create table t1 (i int, row_start timestamp(6) not null default now(), +row_end timestamp(6) not null default '2030-01-01 0:0:0'); +create view v1 as select i from t1 where i < 5 and (row_end = +TIMESTAMP'2030-01-01 0:0:0' or row_end is null); +create procedure pr(x int) select i from v1; +call pr(1); +i +call pr(2); +i +drop procedure pr; +drop view v1; +drop table t1; # end of 5.5 # # Start of 10.1 tests diff --git a/mysql-test/r/dyncol.result b/mysql-test/r/dyncol.result index 23d697835b0..dfbb7a670d6 100644 --- a/mysql-test/r/dyncol.result +++ b/mysql-test/r/dyncol.result @@ -1873,6 +1873,16 @@ SELECT COLUMN_JSON(COLUMN_CREATE('a',1 AS DECIMAL,'b',1 AS DECIMAL)); COLUMN_JSON(COLUMN_CREATE('a',1 AS DECIMAL,'b',1 AS DECIMAL)) {"a":1,"b":1} # +# MDEV-7533: COLUMN_JSON() doesn't escape control characters +# in string values +# +SELECT COLUMN_JSON(COLUMN_CREATE('test','"\\\t\n\Z')) AS json; +json +{"test":"\"\\\u0009\u000A\u001A"} +SELECT COLUMN_JSON(COLUMN_CREATE('test','First line\nSecond line')) AS json; +json +{"test":"First line\u000ASecond line"} +# # end of 10.0 tests # # diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 7ee5a68ca90..c399855bfee 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -743,6 +743,26 @@ txt1 txt2 nnn2 x2 y2 ööö2 mmm2 ùùù2 DROP TABLE t1; # +# MDEV-14743: Server crashes in Item_func_match::init_search +# +CREATE TABLE t1 (f VARCHAR(8)); +INSERT INTO t1 VALUES ('foo'),('bar'); +SELECT 'foo' IN ( SELECT f FROM t1 GROUP BY MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE ) ); +'foo' IN ( SELECT f FROM t1 GROUP BY MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE ) ) +1 +SELECT 'foo' IN ( SELECT f FROM t1 GROUP BY MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE )) as f1, MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE ) as f2 from t1 ; +f1 f2 +1 0 +1 0 +explain extended +SELECT 'foo' IN ( SELECT f FROM t1 GROUP BY MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE )) as f1, MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE ) as f2 from t1 ; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 2 100.00 +2 SUBQUERY t1 ALL NULL NULL NULL NULL 2 100.00 Using where +Warnings: +Note 1003 /* select#1 */ select <expr_cache><'foo'>(<in_optimizer>('foo',<exists>(/* select#2 */ select `test`.`t1`.`f` from `test`.`t1` where <cache>(convert('foo' using latin1)) = `test`.`t1`.`f` or `test`.`t1`.`f` is null having `test`.`t1`.`f` is null))) AS `f1`,(match `test`.`t1`.`f` against ('qux' in boolean mode)) AS `f2` from `test`.`t1` +drop table t1; +# # End of 5.5 tests # CREATE TABLE t1 ( diff --git a/mysql-test/r/func_concat.result b/mysql-test/r/func_concat.result index b87ee7bfc52..9ab6f74653e 100644 --- a/mysql-test/r/func_concat.result +++ b/mysql-test/r/func_concat.result @@ -262,3 +262,9 @@ c2 abcdefghi-abcdefghi DROP TABLE t1; SET optimizer_switch=@save_optimizer_switch; +# +# MDEV-13790 UNHEX() of a somewhat complicated CONCAT() returns NULL +# +SELECT UNHEX(CONCAT('414C2', HEX(8 + ROUND(RAND()*7)), SUBSTR(SHA(UUID()),6,33),HEX(2+ROUND(RAND()*8)))) IS NULL AS c1; +c1 +0 diff --git a/mysql-test/r/func_isnull.result b/mysql-test/r/func_isnull.result index 2dbe3d036f9..15d87997e29 100644 --- a/mysql-test/r/func_isnull.result +++ b/mysql-test/r/func_isnull.result @@ -24,3 +24,87 @@ INSERT INTO t1( id ) VALUES ( NULL ); SELECT t1.id FROM t1 WHERE (id is not null and id is null ); id DROP TABLE t1; +# End of 5.1 tests +# +# MDEV-14911: IS NULL for field from mergeable view +# +CREATE TABLE t1 (d1 datetime NOT NULL); +INSERT INTO t1 VALUES +('0000-00-00 00:00:00'), ('0000-00-00 00:00:00'), ('1979-09-03 20:49:36'); +SELECT * FROM t1; +d1 +0000-00-00 00:00:00 +0000-00-00 00:00:00 +1979-09-03 20:49:36 +SELECT * FROM t1 WHERE d1 IS NULL; +d1 +0000-00-00 00:00:00 +0000-00-00 00:00:00 +EXPLAIN EXTENDED SELECT * FROM t1 WHERE d1 IS NULL; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`d1` AS `d1` from `test`.`t1` where `test`.`t1`.`d1` = 0 +SELECT count(*) FROM t1 WHERE d1 IS NULL; +count(*) +2 +CREATE VIEW v1 AS (SELECT * FROM t1); +SELECT * FROM v1; +d1 +0000-00-00 00:00:00 +0000-00-00 00:00:00 +1979-09-03 20:49:36 +SELECT * FROM v1 WHERE d1 IS NULL; +d1 +0000-00-00 00:00:00 +0000-00-00 00:00:00 +EXPLAIN EXTENDED SELECT * FROM v1 WHERE d1 IS NULL; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where +Warnings: +Note 1003 select `test`.`t1`.`d1` AS `d1` from `test`.`t1` where `test`.`t1`.`d1` = 0 +SELECT count(*) FROM v1 WHERE d1 IS NULL; +count(*) +2 +SET @save_optimizer_switch=@@optimizer_switch; +SET SESSION optimizer_switch='derived_merge=off'; +SELECT count(*) FROM ( SELECT * FROM t1 ) AS a1 WHERE d1 IS NULL; +count(*) +2 +SET SESSION optimizer_switch='derived_merge=on'; +SELECT count(*) FROM ( SELECT * FROM t1 ) AS a1 WHERE d1 IS NULL; +count(*) +2 +SET optimizer_switch=@save_optimizer_switch; +CREATE TABLE t2 (d1 datetime NOT NULL); +INSERT INTO t2 VALUES +('1980-09-03 20:49:36'), ('0000-00-00 00:00:00'), ('1979-09-03 20:49:36'); +SELECT * FROM t2 LEFT JOIN t1 ON t2.d1=t1.d1 WHERE t1.d1 IS NULL; +d1 d1 +0000-00-00 00:00:00 0000-00-00 00:00:00 +0000-00-00 00:00:00 0000-00-00 00:00:00 +1980-09-03 20:49:36 NULL +EXPLAIN EXTENDED +SELECT * FROM t2 LEFT JOIN t1 ON t2.d1=t1.d1 WHERE t1.d1 IS NULL; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) +Warnings: +Note 1003 select `test`.`t2`.`d1` AS `d1`,`test`.`t1`.`d1` AS `d1` from `test`.`t2` left join `test`.`t1` on(`test`.`t1`.`d1` = `test`.`t2`.`d1`) where `test`.`t1`.`d1` = 0 or `test`.`t1`.`d1` is null +SELECT * FROM t2 LEFT JOIN v1 ON t2.d1=v1.d1 WHERE v1.d1 IS NULL; +d1 d1 +0000-00-00 00:00:00 0000-00-00 00:00:00 +0000-00-00 00:00:00 0000-00-00 00:00:00 +1980-09-03 20:49:36 NULL +EXPLAIN EXTENDED +SELECT * FROM t2 LEFT JOIN v1 ON t2.d1=v1.d1 WHERE v1.d1 IS NULL; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 SIMPLE t2 ALL NULL NULL NULL NULL 3 100.00 +1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where; Using join buffer (flat, BNL join) +Warnings: +Note 1003 select `test`.`t2`.`d1` AS `d1`,`test`.`t1`.`d1` AS `d1` from `test`.`t2` left join (`test`.`t1`) on(`test`.`t1`.`d1` = `test`.`t2`.`d1`) where `test`.`t1`.`d1` = 0 or `test`.`t1`.`d1` is null +DROP VIEW v1; +DROP TABLE t1,t2; +# +# End of 5.5 tests +# diff --git a/mysql-test/r/join_cache.result b/mysql-test/r/join_cache.result index 5a404fe46a6..eea397402ad 100644 --- a/mysql-test/r/join_cache.result +++ b/mysql-test/r/join_cache.result @@ -5867,6 +5867,64 @@ set join_buffer_size=default; set join_cache_level = default; DROP TABLE t1,t2; # +# MDEV-14960: BNLH used for materialized semi-join +# +CREATE TABLE t1 (i1 int); +CREATE TABLE t2 (e1 int); +CREATE TABLE t4 (e1 int); +CREATE TABLE t5 (e1 int); +INSERT INTO t1 VALUES +(1),(2),(3),(4),(5),(6),(7),(8); +INSERT INTO t1 SELECT i1+8 FROM t1; +INSERT INTO t1 SELECT i1+16 FROM t1; +INSERT INTO t1 SELECT i1+32 FROM t1; +INSERT INTO t1 SELECT i1+64 FROM t1; +INSERT INTO t2 SELECT * FROM t1; +INSERT INTO t4 SELECT * FROM t1; +INSERT INTO t5 SELECT * FROM t1; +set @save_optimizer_switch= @@optimizer_switch; +SET join_cache_level = 6; +SET join_buffer_size=4096; +SET join_buffer_space_limit=4096; +SET optimizer_switch = 'join_cache_hashed=on,optimize_join_buffer_size=on'; +EXPLAIN SELECT * FROM t1 +WHERE +i1 < 10 AND +i1 IN +(SELECT i1 FROM +(SELECT (t4.e1) i1 FROM t4 +LEFT JOIN t5 ON t4.e1 = t5.e1 +LEFT JOIN (SELECT e1 FROM t2 ) AS d ON t4.e1 = d.e1) a); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 ALL NULL NULL NULL NULL 128 Using where +1 PRIMARY <subquery2> eq_ref distinct_key distinct_key 4 func 1 +2 MATERIALIZED t4 ALL NULL NULL NULL NULL 128 +2 MATERIALIZED t5 hash_ALL NULL #hash#$hj 5 test.t4.e1 128 Using where; Using join buffer (flat, BNLH join) +2 MATERIALIZED t2 hash_ALL NULL #hash#$hj 5 test.t4.e1 128 Using where; Using join buffer (incremental, BNLH join) +SELECT * FROM t1 +WHERE +i1 < 10 AND +i1 IN +(SELECT i1 FROM +(SELECT (t4.e1) i1 FROM t4 +LEFT JOIN t5 ON t4.e1 = t5.e1 +LEFT JOIN (SELECT e1 FROM t2 ) AS d ON t4.e1 = d.e1) a); +i1 +1 +2 +3 +4 +5 +6 +7 +8 +9 +SET join_cache_level = default; +SET join_buffer_size = default; +SET join_buffer_space_limit= default; +set optimizer_switch=@save_optimizer_switch; +DROP TABLE t1,t4,t5,t2; +# # MDEV-5123 Remove duplicated conditions pushed both to join_tab->select_cond and join_tab->cache_select->cond for blocked joins. # set join_cache_level=default; diff --git a/mysql-test/r/mdev_14586.result b/mysql-test/r/mdev_14586.result new file mode 100644 index 00000000000..f6c2095d3cd --- /dev/null +++ b/mysql-test/r/mdev_14586.result @@ -0,0 +1,44 @@ +create table t1(a bit(1), b int auto_increment ,id int, index(a,b)); +insert into t1 values(1,null,1); +insert into t1 values(1,null,2); +insert into t1 values(0,null,3); +insert into t1 values(0,null,4); +select a+0, b as auto_increment , id from t1 order by id; +a+0 auto_increment id +1 1 1 +1 2 2 +0 1 3 +0 2 4 +drop table t1; +create table t1(a int auto_increment, b bit(5) ,id int, index (b,a)); +insert into t1 values(null,b'1',1); +insert into t1 values(null,b'1',2); +insert into t1 values(null,b'11',3); +insert into t1 values(null,b'11',4); +select a as auto_increment, b+0, id from t1 order by id; +auto_increment b+0 id +1 1 1 +2 1 2 +1 3 3 +2 3 4 +drop table t1; +create table t1(a bit(1), b int auto_increment , c bit(1) , d bit(1), id int,index(a,c,b,d)); +insert into t1 values(1,null,1,1,1); +insert into t1 values(1,null,1,1,2); +insert into t1 values(0,null,1,1,3); +insert into t1 values(1,null,0,1,4); +select a+0, b as auto_increment, c+0, d+0, id from t1 order by id; +a+0 auto_increment c+0 d+0 id +1 1 1 1 1 +1 2 1 1 2 +0 1 1 1 3 +1 1 0 1 4 +drop table t1; +CREATE TABLE t1 (b BIT(1), pk INTEGER AUTO_INCREMENT PRIMARY KEY); +ALTER TABLE t1 ADD INDEX(b,pk); +INSERT INTO t1 VALUES (1,b'1'); +ALTER TABLE t1 DROP PRIMARY KEY; +select b+0, pk as auto_increment from t1; +b+0 auto_increment +1 1 +DROP TABLE t1; diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index afea08593a6..1352132b6f3 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -2187,7 +2187,7 @@ col1 int(10) NOT NULL ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(t1); insert into m1 (col1) values (1); insert into m1 (col1) values (1); -ERROR 23000: Duplicate entry '' for key '*UNKNOWN*' +ERROR 23000: Can't write; duplicate key in table 'm1' drop table m1, t1; # # Bug#45800 crash when replacing into a merge table and there is a duplicate @@ -2224,7 +2224,7 @@ CREATE TABLE m1 (c1 INT, c2 INT, UNIQUE (c1)) ENGINE=MRG_MyISAM INSERT_METHOD=LA INSERT INTO m1 VALUES (1,2); # insert the duplicate value into the merge table INSERT INTO m1 VALUES (3,2); -ERROR 23000: Duplicate entry '' for key '*UNKNOWN*' +ERROR 23000: Can't write; duplicate key in table 'm1' DROP TABLE m1,t1; # Try to define MERGE and MyISAM with keys on different columns CREATE TABLE t1 (c1 INT, c2 INT, UNIQUE (c1)); diff --git a/mysql-test/r/myisam_optimize.result b/mysql-test/r/myisam_optimize.result index b769c4ac3e9..f71d524fadb 100644 --- a/mysql-test/r/myisam_optimize.result +++ b/mysql-test/r/myisam_optimize.result @@ -29,3 +29,17 @@ disconnect con2; connection default; drop table t1; set debug_sync='reset'; +# End of 5.5 tests +CREATE TABLE t1 (i INT) ENGINE=MyISAM; +INSERT t1 VALUES (1); +LOCK TABLE t1 WRITE; +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize status OK +SELECT * FROM INFORMATION_SCHEMA.TABLES; +SELECT * FROM t1; +i +1 +UNLOCK TABLES; +DROP TABLE t1; +# End of 10.0 tests diff --git a/mysql-test/r/mysqldump-nl.result b/mysql-test/r/mysqldump-nl.result index db327736551..d2d0e09546b 100644 --- a/mysql-test/r/mysqldump-nl.result +++ b/mysql-test/r/mysqldump-nl.result @@ -124,3 +124,46 @@ v1 1v drop database `mysqltest1 1tsetlqsym`; +create database `test```; +create database `test\`` +\! ls +#`; +show databases like 'test%'; +Database (test%) +test +test\` +\! ls +# +test` + +-- +-- Current Database: `test``` +-- + +/*!40000 DROP DATABASE IF EXISTS `test```*/; + +CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test``` /*!40100 DEFAULT CHARACTER SET latin1 */; + +USE `test```; + +-- +-- Current Database: `test\`` +-- \! ls +-- #` +-- + +/*!40000 DROP DATABASE IF EXISTS `test\`` +\! ls +#`*/; + +CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test\`` +\! ls +#` /*!40100 DEFAULT CHARACTER SET latin1 */; + +USE `test\`` +\! ls +#`; +drop database `test```; +drop database `test\`` +\! ls +#`; diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result index 5a9f2fae1e0..1ca3034c610 100644 --- a/mysql-test/r/order_by.result +++ b/mysql-test/r/order_by.result @@ -2948,6 +2948,52 @@ ORDER BY NULL, @a0 := 3, @a1 := 3, @a2 := 3, @a3 := 3, @a4 := 3, 1 1 2 +# +# mdev-6706: semi-join with duplicate weedout + ORDER BY +# +CREATE TABLE t1 (f1 VARCHAR(3)) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('foo'); +CREATE TABLE t2 (f2 VARCHAR(3)) ENGINE=MyISAM; +INSERT INTO t2 VALUES ('bar'),('baz'); +CREATE TABLE t3 +(i3_key INT, f3_key VARCHAR(3), f3 VARCHAR(3), KEY(f3_key,i3_key)) +ENGINE=MyISAM; +INSERT INTO t3 VALUES (0,'qux','qux'),(8,'bar','bar'); +SELECT CONCAT( f1, f2 ) AS field FROM t1, t2 +WHERE f1 = ANY ( SELECT f1 +FROM t1 +LEFT JOIN ( t3 AS t3a, t3 AS t3b ) +ON ( t3b.f3_key = t3a.f3 ) +WHERE t3a.f3 < f1 OR t3b.f3 != f1 ); +field +foobar +foobaz +SELECT CONCAT( f1, f2 ) AS field FROM t1, t2 +WHERE f1 = ANY ( SELECT f1 +FROM t1 +LEFT JOIN ( t3 AS t3a, t3 AS t3b ) +ON ( t3b.f3_key = t3a.f3 ) +WHERE t3a.f3 < f1 OR t3b.f3 != f1 ) +ORDER BY field; +field +foobar +foobaz +EXPLAIN EXTENDED SELECT CONCAT( f1, f2 ) AS field FROM t1, t2 +WHERE f1 = ANY ( SELECT f1 +FROM t1 +LEFT JOIN ( t3 AS t3a, t3 AS t3b ) +ON ( t3b.f3_key = t3a.f3 ) +WHERE t3a.f3 < f1 OR t3b.f3 != f1 ) +ORDER BY field; +id select_type table type possible_keys key key_len ref rows filtered Extra +1 PRIMARY t1 system NULL NULL NULL NULL 1 100.00 Using temporary; Using filesort +1 PRIMARY t1 system NULL NULL NULL NULL 1 100.00 +1 PRIMARY t2 ALL NULL NULL NULL NULL 2 100.00 +1 PRIMARY t3a ALL NULL NULL NULL NULL 2 100.00 Using where; Start temporary +1 PRIMARY t3b ref f3_key f3_key 6 test.t3a.f3 1 100.00 Using where; End temporary +Warnings: +Note 1003 select concat('foo',`test`.`t2`.`f2`) AS `field` from `test`.`t2` semi join ((`test`.`t3` `t3a` join `test`.`t3` `t3b`)) where `test`.`t3a`.`f3` < 'foo' or `test`.`t3b`.`f3` <> 'foo' order by concat('foo',`test`.`t2`.`f2`) +DROP TABLE t1,t2,t3; End of 5.5 tests # # MDEV-5884: EXPLAIN UPDATE ... ORDER BY LIMIT shows wrong #rows diff --git a/mysql-test/r/partition.result b/mysql-test/r/partition.result index f398ef07d56..1b981284224 100644 --- a/mysql-test/r/partition.result +++ b/mysql-test/r/partition.result @@ -2634,8 +2634,19 @@ alter table t1 drop partition if exists p5; Warnings: Note 1507 Error in list of partitions to DROP DROP TABLE t1; +CREATE TABLE t1 (a INT) ENGINE=MyISAM PARTITION BY RANGE(a) (PARTITION p1 VALUES LESS THAN (0)); +ALTER TABLE t1 ADD PARTITION (PARTITION p2 VALUES LESS THAN (1)); +PREPARE stmt FROM 'ALTER TABLE t1 ADD PARTITION IF NOT EXISTS (PARTITION p2 VALUES LESS THAN (2))'; +EXECUTE stmt; +Warnings: +Note 1517 Duplicate partition name p2 +EXECUTE stmt; +Warnings: +Note 1517 Duplicate partition name p2 +DEALLOCATE PREPARE stmt; +DROP TABLE t1; # -# Start of 10.1 tests +# End of 10.0 tests # # # MDEV-8283 crash in get_mm_leaf with xor on binary col diff --git a/mysql-test/r/partition_innodb.result b/mysql-test/r/partition_innodb.result index c74f25928a9..942455f23ed 100644 --- a/mysql-test/r/partition_innodb.result +++ b/mysql-test/r/partition_innodb.result @@ -900,3 +900,30 @@ SELECT b FROM t1 WHERE b = 0; ERROR HY000: Table definition has changed, please retry transaction disconnect con1; DROP TABLE t1; +# +# Bug#26390658 RENAMING A PARTITIONED TABLE DOES NOT UPDATE +# MYSQL.INNODB_TABLE_STATS +# +CREATE DATABASE test_jfg; +CREATE TABLE test_jfg.test_jfg1 (id int(10) unsigned NOT NULL,PRIMARY +KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=latin1 STATS_PERSISTENT=1; +CREATE TABLE test_jfg.test_jfg2 (id int(10) unsigned NOT NULL,PRIMARY +KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=latin1 STATS_PERSISTENT=1 +PARTITION BY RANGE ( id ) (PARTITION p1000 VALUES LESS THAN (1000) +ENGINE = InnoDB,PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = +InnoDB); +SELECT database_name, table_name FROM mysql.innodb_table_stats WHERE +database_name = 'test_jfg'; +database_name table_name +test_jfg test_jfg1 +test_jfg test_jfg2#P#p1000 +test_jfg test_jfg2#P#pmax +RENAME TABLE test_jfg.test_jfg1 TO test_jfg.test_jfg11; +RENAME TABLE test_jfg.test_jfg2 TO test_jfg.test_jfg12; +SELECT database_name, table_name FROM mysql.innodb_table_stats WHERE +database_name = 'test_jfg'; +database_name table_name +test_jfg test_jfg11 +test_jfg test_jfg12#P#p1000 +test_jfg test_jfg12#P#pmax +DROP DATABASE test_jfg; diff --git a/mysql-test/r/query_cache_debug.result b/mysql-test/r/query_cache_debug.result index afc1eb3d135..2a54f073974 100644 --- a/mysql-test/r/query_cache_debug.result +++ b/mysql-test/r/query_cache_debug.result @@ -248,3 +248,39 @@ RESET QUERY CACHE; DROP TABLE t1; SET GLOBAL query_cache_size= DEFAULT; SET GLOBAL query_cache_type= DEFAULT; +# +# MDEV-14526: MariaDB keeps crashing under load when +# query_cache_type is changed +# +CREATE TABLE t1 ( +`id` int(10) NOT NULL AUTO_INCREMENT, +`k` int(10) default '0', +PRIMARY KEY (`id`)) +ENGINE=MyISAM; +INSERT IGNORE INTO t1 VALUES +(NULL,1),(NULL,8),(NULL,NULL),(NULL,NULL),(NULL,4),(NULL,9),(NULL,7), +(NULL,3),(NULL,NULL),(NULL,2),(NULL,3),(NULL,NULL),(NULL,2),(NULL,7), +(NULL,1),(NULL,2),(NULL,4),(NULL,NULL),(NULL,1),(NULL,1),(NULL,4); +SET GLOBAL query_cache_size= 1024*1024; +SET GLOBAL query_cache_type= 1; +connect con2,localhost,root,,test; +connect con1,localhost,root,,test; +set debug_sync="wait_in_query_cache_store_query SIGNAL parked WAIT_FOR go"; +SELECT DISTINCT id FROM t1 WHERE id BETWEEN 5603 AND 16218 ORDER BY k; +connection default; +set debug_sync="now WAIT_FOR parked"; +connection con2; +SET GLOBAL query_cache_type= 0; +connection default; +set debug_sync="now SIGNAL go"; +connection con1; +id +connection con2; +disconnect con1; +disconnect con2; +connection default; +set debug_sync= 'RESET'; +DROP TABLE t1; +SEt GLOBAL query_cache_size= DEFAULT; +SEt GLOBAL query_cache_type= DEFAULT; +# End of 5.5 tests diff --git a/mysql-test/r/repair.result b/mysql-test/r/repair.result index 79ee0c7a9b8..8d48d2f8848 100644 --- a/mysql-test/r/repair.result +++ b/mysql-test/r/repair.result @@ -114,7 +114,7 @@ test.t1 repair status OK SET myisam_repair_threads=@@global.myisam_repair_threads; SET myisam_sort_buffer_size=@@global.myisam_sort_buffer_size; DROP TABLE t1; -End of 4.1 tests +# End of 4.1 tests # Test with a saved table from 4.1 SHOW TABLE STATUS LIKE 't1'; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment @@ -150,6 +150,7 @@ SELECT * FROM t1; id 1 DROP TABLE t1; +# End of 5.0 tests DROP TABLE IF EXISTS tt1; CREATE TEMPORARY TABLE tt1 (c1 INT); REPAIR TABLE tt1 USE_FRM; @@ -214,3 +215,17 @@ Table Op Msg_type Msg_text test.v1 repair status OK drop view v1; drop table t1; +# End of 5.5 tests +CREATE TABLE t1 (i INT) ENGINE=MyISAM; +INSERT t1 VALUES (1); +LOCK TABLE t1 WRITE; +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +SELECT * FROM INFORMATION_SCHEMA.TABLES; +SELECT * FROM t1; +i +1 +UNLOCK TABLES; +DROP TABLE t1; +# End of 10.0 tests diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 9a9042bc8c9..ca6a3b495aa 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -8128,6 +8128,129 @@ SET @aux = f1(); DROP FUNCTION f1; DROP VIEW v1; DROP TABLE t1; +# +# MDEV-14857: problem with 10.2.11 server crashing when +# executing stored procedure +# +SET max_sp_recursion_depth=10; +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (b INT); +CREATE PROCEDURE proc_0() +BEGIN +CALL empty_1(); +CALL proc_1(); +END || +CREATE PROCEDURE proc_1() +BEGIN +CALL proc_2(); +CALL proc_3(); +CALL proc_4(); +CALL proc_5(); +END || +CREATE PROCEDURE proc_2() +CALL proc_6(); +|| +CREATE PROCEDURE proc_3() +BEGIN +CALL empty_2(); +CALL empty_3(); +END || +CREATE PROCEDURE proc_4() +CALL proc_7(); +|| +CREATE PROCEDURE proc_5() +CALL proc_select(); +|| +CREATE PROCEDURE proc_6() +BEGIN +CALL empty_4(); +CALL empty_5(); +CALL empty_6(); +CALL empty_7(); +CALL proc_8(); +END || +CREATE PROCEDURE proc_7() +CALL proc_9('foo'); +|| +CREATE PROCEDURE proc_8() +CALL proc_10(); +|| +CREATE PROCEDURE proc_9(IN opt VARCHAR(40)) +IF LEFT(opt,1) <> '_' THEN +CALL proc_11(); +END IF; +|| +CREATE PROCEDURE proc_10() +CALL proc_12(); +|| +CREATE PROCEDURE proc_11() +BEGIN +CALL empty_8(); +CALL empty_9(); +CALL empty_10(); +CALL proc_13(); +END || +CREATE PROCEDURE proc_12() +BEGIN +CALL empty_11(); +CALL empty_12(); +CALL empty_13(); +END || +CREATE PROCEDURE proc_13() +BEGIN +CALL proc_9('_bar'); +CALL empty_14(); +END || +CREATE PROCEDURE empty_1() BEGIN END ; +CREATE PROCEDURE empty_2() BEGIN END ; +CREATE PROCEDURE empty_3() BEGIN END ; +CREATE PROCEDURE empty_4() BEGIN END ; +CREATE PROCEDURE empty_5() BEGIN END ; +CREATE PROCEDURE empty_6() BEGIN END ; +CREATE PROCEDURE empty_7() BEGIN END ; +CREATE PROCEDURE empty_8() BEGIN END ; +CREATE PROCEDURE empty_9() BEGIN END ; +CREATE PROCEDURE empty_10() BEGIN END ; +CREATE PROCEDURE empty_11() BEGIN END ; +CREATE PROCEDURE empty_12() BEGIN END ; +CREATE PROCEDURE empty_13() BEGIN END ; +CREATE PROCEDURE empty_14() BEGIN END ; +CREATE PROCEDURE proc_select() +SELECT * FROM t1 WHERE NOT EXISTS ( SELECT * FROM t2) +; +CALL proc_0(); +a +DROP PROCEDURE empty_1; +DROP PROCEDURE empty_2; +DROP PROCEDURE empty_3; +DROP PROCEDURE empty_4; +DROP PROCEDURE empty_5; +DROP PROCEDURE empty_6; +DROP PROCEDURE empty_7; +DROP PROCEDURE empty_8; +DROP PROCEDURE empty_9; +DROP PROCEDURE empty_10; +DROP PROCEDURE empty_11; +DROP PROCEDURE empty_12; +DROP PROCEDURE empty_13; +DROP PROCEDURE empty_14; +DROP PROCEDURE proc_0; +DROP PROCEDURE proc_1; +DROP PROCEDURE proc_2; +DROP PROCEDURE proc_3; +DROP PROCEDURE proc_4; +DROP PROCEDURE proc_5; +DROP PROCEDURE proc_6; +DROP PROCEDURE proc_7; +DROP PROCEDURE proc_8; +DROP PROCEDURE proc_9; +DROP PROCEDURE proc_10; +DROP PROCEDURE proc_11; +DROP PROCEDURE proc_12; +DROP PROCEDURE proc_13; +DROP PROCEDURE proc_select; +DROP TABLE t1, t2; +SET max_sp_recursion_depth=default; #End of 10.1 tests # # MDEV-11081: CURSOR for query with GROUP BY diff --git a/mysql-test/r/thread_id_overflow.result b/mysql-test/r/thread_id_overflow.result new file mode 100644 index 00000000000..8303debb246 --- /dev/null +++ b/mysql-test/r/thread_id_overflow.result @@ -0,0 +1,23 @@ +connect con1, localhost,root; +disconnect con1; +connect con2, localhost,root; +connection con2; +connection default; +SET @orig_debug=@@debug_dbug; +SET GLOBAL DEBUG_DBUG='+d,thread_id_overflow'; +connect con3, localhost,root; +connection con3; +SELECT CONNECTION_ID(); +CONNECTION_ID() +4294967294 +connection default; +SET GLOBAL DEBUG_DBUG=@orig_debug; +connect con4, localhost,root; +connection con4; +select IF(connection_id() - max_id = 1,'Good','Bad') as result; +result +Good +disconnect con4; +disconnect con3; +disconnect con2; +connection default; diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index b193f032146..65384d3775a 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -2094,6 +2094,46 @@ avg(f) sub 31.5000 0 1.5000 1 drop table t1,t2,t3; +# +# MDEV-14715 Assertion `!table || (!table->read_set || +# bitmap_is_set(table->read_set, field_index))' +# failed in Field_num::val_decimal +# +CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM; +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (1, NULL),(3, 4); +(SELECT a, sum(a) AS f FROM v1 group by a ORDER BY b + sum(a)) +UNION +(SELECT 2, 2); +a f +1 1 +3 3 +2 2 +(SELECT a, sum(a) AS f FROM v1 group by a ORDER BY b + 1) +UNION +(SELECT 2, 2); +a f +1 1 +3 3 +2 2 +SELECT a, b FROM t1 +UNION +(SELECT a, VAR_POP(a) AS f FROM v1 GROUP BY a ORDER BY b/a ); +a b +1 NULL +3 4.0000 +1 0.0000 +3 0.0000 +DROP TABLE t1; +(SELECT a, sum(a) AS f FROM v1 group by a ORDER BY b + 1) +UNION +(SELECT 2, 2); +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +DROP VIEW v1; +(SELECT a, sum(a) AS f FROM v1 group by a ORDER BY b + 1) +UNION +(SELECT 2, 2); +ERROR 42S02: Table 'test.v1' doesn't exist End of 5.5 tests # # WL#1763 Avoid creating temporary table in UNION ALL diff --git a/mysql-test/r/update_innodb.result b/mysql-test/r/update_innodb.result index 5fcc584035a..0a85c6dab3e 100644 --- a/mysql-test/r/update_innodb.result +++ b/mysql-test/r/update_innodb.result @@ -30,6 +30,16 @@ UPDATE t1 a JOIN t2 b ON a.c1 = b.c1 JOIN v1 vw ON b.c2 = vw.c1 JOIN t3 del ON v drop view v1; drop table t1,t2,t3,t4; # +# MDEV-14862: Server crashes in Bitmap<64u>::merge / add_key_field +# +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE TABLE t2 (b INT) ENGINE=InnoDB; +DELETE FROM v1 WHERE a IN ( SELECT a FROM t2 ); +DELETE FROM v1 WHERE (a,a) IN ( SELECT a,a FROM t2 ); +drop view v1; +drop table t1,t2; +# # MDEV-10232 Scalar result of subquery changes after adding an outer select stmt # CREATE TABLE t1 ( diff --git a/mysql-test/r/xa.result b/mysql-test/r/xa.result index 6c1ff867f89..5d78bb68c8c 100644 --- a/mysql-test/r/xa.result +++ b/mysql-test/r/xa.result @@ -281,6 +281,17 @@ a 1 DROP TABLE t1; # +# MDEV-14609 XA Transction unable to ROLLBACK TO SAVEPOINT +# +CREATE TABLE t1 (c1 INT) ENGINE=INNODB; +XA START 'xa1'; +SAVEPOINT savepoint1; +INSERT INTO t1 (c1) VALUES (1),(2),(3),(4); +ROLLBACK TO SAVEPOINT savepoint1; +XA END 'xa1'; +XA ROLLBACK 'xa1'; +DROP TABLE t1; +# # Bug#12352846 - TRANS_XA_START(THD*): # ASSERTION THD->TRANSACTION.XID_STATE.XID.IS_NULL() # FAILED diff --git a/mysql-test/r/xml.result b/mysql-test/r/xml.result index 23a2f8b62b8..2cd70c08a94 100644 --- a/mysql-test/r/xml.result +++ b/mysql-test/r/xml.result @@ -1274,6 +1274,18 @@ c1 c2 2 b2 DROP TABLE t1; # +# MDEV-15118 ExtractValue(xml,something_complex) does not work +# +CREATE TABLE t1 (a TEXT); +INSERT INTO t1 VALUES (CONCAT('<a>aaa</a>')); +SELECT ExtractValue(a, '/a') AS a FROM t1; +a +aaa +SELECT ExtractValue(a, FROM_BASE64(TO_BASE64('/a'))) AS a FROM t1; +a +aaa +DROP TABLE t1; +# # End of 10.0 tests # # diff --git a/mysql-test/suite/galera/disabled.def b/mysql-test/suite/galera/disabled.def index 793d389c5d3..0b5aa239180 100644 --- a/mysql-test/suite/galera/disabled.def +++ b/mysql-test/suite/galera/disabled.def @@ -54,7 +54,6 @@ galera_pc_ignore_sb : MDEV-13549 Galera test failures 10.1 galera_lock_table : MDEV-13549 Galera test failures 10.1 MW-284 : MDEV-13549 Galera test failures 10.1 galera_as_slave : MDEV-13549 Galera test failures 10.1 -galera_var_innodb_disallow_writes : MDEV-10949 galera_kill_applier : race condition at the start of the test GAL-480 : "Lost connection to MySQL" MW-328C: MDEV-13549 Galera test failures 10.1 @@ -62,3 +61,4 @@ MW-328A: MDEV-13549 Galera test failures 10.1 MW-328B: MDEV-13549 Galera test failures 10.1 MW-328: MDEV-13549 Galera test failures 10.1 galera_suspend_slave: MDEV-13549 Galera test failures 10.1 +galera_ist_progress: MDEV-15236 galera_ist_progress fails when trying to read transfer status diff --git a/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result b/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result index 5377a0af1b6..4db4e539c50 100644 --- a/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result +++ b/mysql-test/suite/galera/r/galera_var_innodb_disallow_writes.result @@ -5,6 +5,12 @@ CREATE TABLE t1 (f1 INTEGER) Engine=InnoDB; SET GLOBAL innodb_disallow_writes=ON; INSERT INTO t1 VALUES (1);; connection node_1a; +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +0 +SELECT COUNT(*) = 1 FROM t1; +COUNT(*) = 1 +0 SET GLOBAL innodb_disallow_writes=OFF; connection node_1; SELECT COUNT(*) = 1 FROM t1; diff --git a/mysql-test/suite/galera/t/galera_var_innodb_disallow_writes.test b/mysql-test/suite/galera/t/galera_var_innodb_disallow_writes.test index 3606075e7a8..65b55435a9e 100644 --- a/mysql-test/suite/galera/t/galera_var_innodb_disallow_writes.test +++ b/mysql-test/suite/galera/t/galera_var_innodb_disallow_writes.test @@ -18,8 +18,10 @@ SET GLOBAL innodb_disallow_writes=ON; --send INSERT INTO t1 VALUES (1); --connection node_1a +SELECT COUNT(*) = 1 FROM t1; let $wait_condition = SELECT 1 FROM INFORMATION_SCHEMA.PROCESSLIST WHERE INFO = 'INSERT INTO t1 VALUES (1)' AND State = 'Commit'; --source include/wait_condition.inc +SELECT COUNT(*) = 1 FROM t1; SET GLOBAL innodb_disallow_writes=OFF; diff --git a/mysql-test/suite/galera_3nodes/include/have_ipv6.inc b/mysql-test/suite/galera_3nodes/include/have_ipv6.inc new file mode 100644 index 00000000000..560cad03350 --- /dev/null +++ b/mysql-test/suite/galera_3nodes/include/have_ipv6.inc @@ -0,0 +1,15 @@ +# Check if ipv6 is available. +# +--disable_query_log +--disable_result_log +connect (checkcon123456789,::1,root,,test); +if($mysql_errno) +{ + skip No IPv6 support; +} +connection default; +disconnect checkcon123456789; +--enable_result_log +--enable_query_log +# end check + diff --git a/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.test b/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.test index a6660bd08d1..cc3f42c7290 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.test +++ b/mysql-test/suite/galera_3nodes/t/galera_innobackupex_backup.test @@ -16,7 +16,7 @@ SELECT COUNT(*) = 10 FROM t1; --exec innobackupex --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group=mysqld.2 $MYSQL_TMP_DIR/innobackupex_backup --galera-info --port=$NODE_MYPORT_2 --host=127.0.0.1 --no-timestamp > $MYSQL_TMP_DIR/innobackupex-backup.log --exec innobackupex --defaults-file=$MYSQLTEST_VARDIR/my.cnf --defaults-group=mysqld.2 $MYSQL_TMP_DIR/innobackupex_backup --apply-log --galera-info --port=$NODE_MYPORT_2 --host=127.0.0.1 --no-timestamp > $MYSQL_TMP_DIR/innobackupex-apply.log ---source include/kill_galera.inc +--source ../galera/include/kill_galera.inc --sleep 1 --connection node_1 diff --git a/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.test b/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.test index 7c9991e68c4..88d0cfba4f4 100644 --- a/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.test +++ b/mysql-test/suite/galera_3nodes/t/galera_safe_to_bootstrap.test @@ -108,7 +108,7 @@ SET SESSION wsrep_on = OFF; --let $wait_condition = SELECT VARIABLE_VALUE = 1 FROM INFORMATION_SCHEMA.GLOBAL_STATUS WHERE VARIABLE_NAME = 'wsrep_cluster_size'; --source include/wait_condition.inc ---source include/kill_galera.inc +--source ../galera/include/kill_galera.inc # # Only node #1 should have safe_to_bootstrap: 1 diff --git a/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result b/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result index ac4be0dcc6c..309d8e8f04a 100644 --- a/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result +++ b/mysql-test/suite/gcol/r/innodb_virtual_debug_purge.result @@ -145,7 +145,8 @@ connection default; update t set a = repeat('m', 16000) where a like "aaa%"; connect lock_table, localhost, root; lock table t write; -disconnect prevent_purge; +connection prevent_purge; +commit; connection default; InnoDB 0 transactions not purged disconnect lock_table; @@ -154,5 +155,28 @@ commit; InnoDB 0 transactions not purged set global debug_dbug=@old_dbug; drop table t; +# +# MDEV-15165 InnoDB purge for index on virtual column +# is trying to access an incomplete record +# +CREATE TABLE t1( +u INT PRIMARY KEY, b BLOB, ug INT GENERATED ALWAYS AS (u) VIRTUAL, +INDEX bug(b(100),ug) +) ENGINE=InnoDB; +INSERT INTO t1 (u,b) VALUES(1,REPEAT('a',16384)); +connection prevent_purge; +start transaction with consistent snapshot; +connection default; +DELETE FROM t1; +SET DEBUG_SYNC='blob_write_middle SIGNAL halfway WAIT_FOR purged'; +INSERT INTO t1 (u,b) VALUES(1,REPEAT('a',16384)); +connection prevent_purge; +SET DEBUG_SYNC='now WAIT_FOR halfway'; +COMMIT; +InnoDB 0 transactions not purged +SET DEBUG_SYNC='now SIGNAL purged'; +disconnect prevent_purge; +connection default; +DROP TABLE t1; set debug_sync=reset; SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test b/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test index 1862de268af..ad733eee3a7 100644 --- a/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test +++ b/mysql-test/suite/gcol/t/innodb_virtual_debug_purge.test @@ -184,7 +184,8 @@ connection default; update t set a = repeat('m', 16000) where a like "aaa%"; connect(lock_table, localhost, root); lock table t write; -disconnect prevent_purge; +connection prevent_purge; +commit; connection default; --source ../../innodb/include/wait_all_purged.inc disconnect lock_table; @@ -194,6 +195,32 @@ commit; set global debug_dbug=@old_dbug; drop table t; +--echo # +--echo # MDEV-15165 InnoDB purge for index on virtual column +--echo # is trying to access an incomplete record +--echo # +CREATE TABLE t1( + u INT PRIMARY KEY, b BLOB, ug INT GENERATED ALWAYS AS (u) VIRTUAL, + INDEX bug(b(100),ug) +) ENGINE=InnoDB; +INSERT INTO t1 (u,b) VALUES(1,REPEAT('a',16384)); +connection prevent_purge; +start transaction with consistent snapshot; +connection default; +DELETE FROM t1; +SET DEBUG_SYNC='blob_write_middle SIGNAL halfway WAIT_FOR purged'; +send INSERT INTO t1 (u,b) VALUES(1,REPEAT('a',16384)); +connection prevent_purge; +SET DEBUG_SYNC='now WAIT_FOR halfway'; +COMMIT; +--source ../../innodb/include/wait_all_purged.inc +SET DEBUG_SYNC='now SIGNAL purged'; +disconnect prevent_purge; + +connection default; +reap; +DROP TABLE t1; + --source include/wait_until_count_sessions.inc set debug_sync=reset; SET GLOBAL innodb_purge_rseg_truncate_frequency = @saved_frequency; diff --git a/mysql-test/suite/innodb/r/foreign_key.result b/mysql-test/suite/innodb/r/foreign_key.result index da0e16b86ac..e569fc7dba7 100644 --- a/mysql-test/suite/innodb/r/foreign_key.result +++ b/mysql-test/suite/innodb/r/foreign_key.result @@ -263,3 +263,46 @@ SELECT * FROM t2; id ref_id f 2 2 20 DROP TABLE t2, t1; +# +# MDEV-15199 Referential integrity broken in ON DELETE CASCADE +# +CREATE TABLE member (id int AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO member VALUES (1); +CREATE TABLE address ( +id int AUTO_INCREMENT PRIMARY KEY, +member_id int NOT NULL, +KEY address_FI_1 (member_id), +CONSTRAINT address_FK_1 FOREIGN KEY (member_id) REFERENCES member (id) +ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB; +INSERT INTO address VALUES (2,1); +CREATE TABLE payment_method ( +id int AUTO_INCREMENT PRIMARY KEY, +member_id int NOT NULL, +cardholder_address_id int DEFAULT NULL, +KEY payment_method_FI_1 (member_id), +KEY payment_method_FI_2 (cardholder_address_id), +CONSTRAINT payment_method_FK_1 FOREIGN KEY (member_id) REFERENCES member (id) ON DELETE CASCADE ON UPDATE CASCADE, +CONSTRAINT payment_method_FK_2 FOREIGN KEY (cardholder_address_id) REFERENCES address (id) ON DELETE SET NULL ON UPDATE CASCADE +) ENGINE=InnoDB; +INSERT INTO payment_method VALUES (3,1,2); +BEGIN; +UPDATE member SET id=42; +SELECT * FROM member; +id +42 +SELECT * FROM address; +id member_id +2 42 +SELECT * FROM payment_method; +id member_id cardholder_address_id +3 42 2 +DELETE FROM member; +COMMIT; +SELECT * FROM member; +id +SELECT * FROM address; +id member_id +SELECT * FROM payment_method; +id member_id cardholder_address_id +DROP TABLE payment_method,address,member; diff --git a/mysql-test/suite/innodb/r/innodb-index-online-fk.result b/mysql-test/suite/innodb/r/innodb-index-online-fk.result index 359ce4a717c..4bd4b060ab3 100644 --- a/mysql-test/suite/innodb/r/innodb-index-online-fk.result +++ b/mysql-test/suite/innodb/r/innodb-index-online-fk.result @@ -86,6 +86,7 @@ child CREATE TABLE `child` ( DELETE FROM parent where a = 1; SELECT * FROM child; a1 a2 +1 NULL 2 3 10 20 SET foreign_key_checks = 0; diff --git a/mysql-test/suite/innodb/r/innodb-replace-debug.result b/mysql-test/suite/innodb/r/innodb-replace-debug.result index 84bc9dc9769..989fb055cbc 100644 --- a/mysql-test/suite/innodb/r/innodb-replace-debug.result +++ b/mysql-test/suite/innodb/r/innodb-replace-debug.result @@ -4,10 +4,11 @@ create table t1 (f1 int primary key, f2 int, f3 int, unique key k1(f2), key k2(f3)) engine=innodb; insert into t1 values (14, 24, 34); -set @@debug_dbug = '+d,row_ins_sec_index_entry_timeout'; +set @old_dbug= @@session.debug_dbug; +set debug_dbug = '+d,row_ins_sec_index_entry_timeout'; replace into t1 values (14, 25, 34); select * from t1; f1 f2 f3 14 25 34 drop table t1; -set @@debug_dbug = '-d,row_ins_sec_index_entry_timeout'; +set debug_dbug = @old_dbug; diff --git a/mysql-test/suite/innodb/r/innodb.result b/mysql-test/suite/innodb/r/innodb.result index 656484af89b..ed8720a0df9 100644 --- a/mysql-test/suite/innodb/r/innodb.result +++ b/mysql-test/suite/innodb/r/innodb.result @@ -1,3 +1,5 @@ +create temporary table t (a char(1) character set filename) engine=innodb; +drop temporary table t; set optimizer_switch = 'mrr=on,mrr_sort_keys=on,index_condition_pushdown=on'; drop table if exists t1,t2,t3,t4; drop database if exists mysqltest; @@ -1318,80 +1320,17 @@ INSERT INTO t2 VALUES (10, 'old'), (20, 'other'); UPDATE t1 SET c1 = 'other' WHERE c1 = 'old'; ERROR 23000: Foreign key constraint for table 't1', record 'other-somevalu' would lead to a duplicate entry in table 't2', key 'c1' DROP TABLE t2,t1; -call mtr.add_suppression("Cannot delete/update rows with cascading foreign key constraints that exceed max depth of 255. Please drop excessive foreign constraints and try again"); +call mtr.add_suppression("Cannot delete/update rows with cascading foreign key constraints that exceed max depth of 15\\. Please drop excessive foreign constraints and try again"); create table t1( id int primary key, pid int, index(pid), foreign key(pid) references t1(id) on delete cascade) engine=innodb; -insert into t1 values -( 0, 0), ( 1, 0), ( 2, 1), ( 3, 2), -( 4, 3), ( 5, 4), ( 6, 5), ( 7, 6), -( 8, 7), ( 9, 8), ( 10, 9), ( 11, 10), -( 12, 11), ( 13, 12), ( 14, 13), ( 15, 14), -( 16, 15), ( 17, 16), ( 18, 17), ( 19, 18), -( 20, 19), ( 21, 20), ( 22, 21), ( 23, 22), -( 24, 23), ( 25, 24), ( 26, 25), ( 27, 26), -( 28, 27), ( 29, 28), ( 30, 29), ( 31, 30), -( 32, 31), ( 33, 32), ( 34, 33), ( 35, 34), -( 36, 35), ( 37, 36), ( 38, 37), ( 39, 38), -( 40, 39), ( 41, 40), ( 42, 41), ( 43, 42), -( 44, 43), ( 45, 44), ( 46, 45), ( 47, 46), -( 48, 47), ( 49, 48), ( 50, 49), ( 51, 50), -( 52, 51), ( 53, 52), ( 54, 53), ( 55, 54), -( 56, 55), ( 57, 56), ( 58, 57), ( 59, 58), -( 60, 59), ( 61, 60), ( 62, 61), ( 63, 62), -( 64, 63), ( 65, 64), ( 66, 65), ( 67, 66), -( 68, 67), ( 69, 68), ( 70, 69), ( 71, 70), -( 72, 71), ( 73, 72), ( 74, 73), ( 75, 74), -( 76, 75), ( 77, 76), ( 78, 77), ( 79, 78), -( 80, 79), ( 81, 80), ( 82, 81), ( 83, 82), -( 84, 83), ( 85, 84), ( 86, 85), ( 87, 86), -( 88, 87), ( 89, 88), ( 90, 89), ( 91, 90), -( 92, 91), ( 93, 92), ( 94, 93), ( 95, 94), -( 96, 95), ( 97, 96), ( 98, 97), ( 99, 98), -(100, 99), (101, 100), (102, 101), (103, 102), -(104, 103), (105, 104), (106, 105), (107, 106), -(108, 107), (109, 108), (110, 109), (111, 110), -(112, 111), (113, 112), (114, 113), (115, 114), -(116, 115), (117, 116), (118, 117), (119, 118), -(120, 119), (121, 120), (122, 121), (123, 122), -(124, 123), (125, 124), (126, 125), (127, 126), -(128, 127), (129, 128), (130, 129), (131, 130), -(132, 131), (133, 132), (134, 133), (135, 134), -(136, 135), (137, 136), (138, 137), (139, 138), -(140, 139), (141, 140), (142, 141), (143, 142), -(144, 143), (145, 144), (146, 145), (147, 146), -(148, 147), (149, 148), (150, 149), (151, 150), -(152, 151), (153, 152), (154, 153), (155, 154), -(156, 155), (157, 156), (158, 157), (159, 158), -(160, 159), (161, 160), (162, 161), (163, 162), -(164, 163), (165, 164), (166, 165), (167, 166), -(168, 167), (169, 168), (170, 169), (171, 170), -(172, 171), (173, 172), (174, 173), (175, 174), -(176, 175), (177, 176), (178, 177), (179, 178), -(180, 179), (181, 180), (182, 181), (183, 182), -(184, 183), (185, 184), (186, 185), (187, 186), -(188, 187), (189, 188), (190, 189), (191, 190), -(192, 191), (193, 192), (194, 193), (195, 194), -(196, 195), (197, 196), (198, 197), (199, 198), -(200, 199), (201, 200), (202, 201), (203, 202), -(204, 203), (205, 204), (206, 205), (207, 206), -(208, 207), (209, 208), (210, 209), (211, 210), -(212, 211), (213, 212), (214, 213), (215, 214), -(216, 215), (217, 216), (218, 217), (219, 218), -(220, 219), (221, 220), (222, 221), (223, 222), -(224, 223), (225, 224), (226, 225), (227, 226), -(228, 227), (229, 228), (230, 229), (231, 230), -(232, 231), (233, 232), (234, 233), (235, 234), -(236, 235), (237, 236), (238, 237), (239, 238), -(240, 239), (241, 240), (242, 241), (243, 242), -(244, 243), (245, 244), (246, 245), (247, 246), -(248, 247), (249, 248), (250, 249), (251, 250), -(252, 251), (253, 252), (254, 253), (255, 254); +insert into t1 values(0,0),(1,0),(2,1),(3,2),(4,3),(5,4),(6,5),(7,6), +(8,7),(9,8),(10,9),(11,10),(12,11),(13,12),(14,13),(15,14); delete from t1 where id=0; Got one of the listed errors -delete from t1 where id=255; +delete from t1 where id=15; delete from t1 where id=0; drop table t1; CREATE TABLE t1 (col1 int(1))ENGINE=InnoDB; @@ -1756,10 +1695,10 @@ variable_value 16384 SELECT variable_value - @innodb_rows_deleted_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_deleted'; variable_value - @innodb_rows_deleted_orig -311 +71 SELECT variable_value - @innodb_rows_inserted_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_inserted'; variable_value - @innodb_rows_inserted_orig -1204 +964 SELECT variable_value - @innodb_rows_updated_orig FROM information_schema.global_status WHERE LOWER(variable_name) = 'innodb_rows_updated'; variable_value - @innodb_rows_updated_orig 866 diff --git a/mysql-test/suite/innodb/r/innodb_buffer_pool_resize.result b/mysql-test/suite/innodb/r/innodb_buffer_pool_resize.result new file mode 100644 index 00000000000..667d31a0b69 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_buffer_pool_resize.result @@ -0,0 +1,34 @@ +set global innodb_adaptive_hash_index=ON; +select @@innodb_buffer_pool_size; +@@innodb_buffer_pool_size +8388608 +set global innodb_buffer_pool_size = 10485760; +Warnings: +Warning 1292 Truncated incorrect innodb_buffer_pool_size value: '10485760' +select @@innodb_buffer_pool_size; +@@innodb_buffer_pool_size +16777216 +create table t1 (id int not null, val int not null default '0', primary key (id)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +create or replace view view0 as select 1 union all select 1; +set @`v_id` := 0; +set @`v_val` := 0; +replace into t1 select (@`v_id` := (@`v_id` + 4) mod 4294967296) as id, (@`v_val` := (@`v_val` + 4) mod 4294967296) as val from view0 v0, view0 v1, view0 v2, view0 v3, view0 v4, view0 v5, view0 v6, view0 v7, view0 v8, view0 v9, view0 v10, view0 v11, view0 v12, view0 v13, view0 v14, view0 v15, view0 v16, view0 v17; +set global innodb_buffer_pool_size = 7340032; +Warnings: +Warning 1292 Truncated incorrect innodb_buffer_pool_size value: '7340032' +select @@innodb_buffer_pool_size; +@@innodb_buffer_pool_size +8388608 +select count(val) from t1; +count(val) +262144 +set global innodb_adaptive_hash_index=OFF; +set global innodb_buffer_pool_size = 25165824; +select @@innodb_buffer_pool_size; +@@innodb_buffer_pool_size +25165824 +select count(val) from t1; +count(val) +262144 +drop table t1; +drop view view0; diff --git a/mysql-test/suite/innodb/r/innodb_buffer_pool_resize_with_chunks.result b/mysql-test/suite/innodb/r/innodb_buffer_pool_resize_with_chunks.result new file mode 100644 index 00000000000..4bf244c9588 --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_buffer_pool_resize_with_chunks.result @@ -0,0 +1,26 @@ +select @@innodb_buffer_pool_chunk_size; +@@innodb_buffer_pool_chunk_size +2097152 +create table t1 (id int not null, val int not null default '0', primary key (id)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +create or replace view view0 as select 1 union all select 1; +set @`v_id` := 0; +set @`v_val` := 0; +replace into t1 select (@`v_id` := (@`v_id` + 4) mod 4294967296) as id, (@`v_val` := (@`v_val` + 4) mod 4294967296) as val from view0 v0, view0 v1, view0 v2, view0 v3, view0 v4, view0 v5, view0 v6, view0 v7, view0 v8, view0 v9, view0 v10, view0 v11, view0 v12, view0 v13, view0 v14, view0 v15, view0 v16, view0 v17; +set global innodb_buffer_pool_size = 7340032; +Warnings: +Warning 1292 Truncated incorrect innodb_buffer_pool_size value: '7340032' +select count(val) from t1; +count(val) +262144 +set global innodb_buffer_pool_size = 16777216; +select count(val) from t1; +count(val) +262144 +drop table t1; +drop view view0; +set global innodb_buffer_pool_size = 1048576; +Warnings: +Warning 1292 Truncated incorrect innodb_buffer_pool_size value: '1048576' +select @@innodb_buffer_pool_size; +@@innodb_buffer_pool_size +6291456 diff --git a/mysql-test/suite/innodb/r/innodb_corrupt_bit.result b/mysql-test/suite/innodb/r/innodb_corrupt_bit.result index d614ebff751..2000db03efa 100644 --- a/mysql-test/suite/innodb/r/innodb_corrupt_bit.result +++ b/mysql-test/suite/innodb/r/innodb_corrupt_bit.result @@ -16,18 +16,15 @@ INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+1,z+1 FROM corrupt_bit_test_ā; select count(*) from corrupt_bit_test_ā; count(*) 2 -SET SESSION debug="+d,dict_set_index_corrupted"; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +SET @save_dbug = @@SESSION.debug_dbug; +SET debug_dbug = '+d,dict_set_index_corrupted'; check table corrupt_bit_test_ā; Table Op Msg_type Msg_text test.corrupt_bit_test_ā check Warning InnoDB: Index idx is marked as corrupted test.corrupt_bit_test_ā check Warning InnoDB: Index idxā is marked as corrupted test.corrupt_bit_test_ā check Warning InnoDB: Index idxē is marked as corrupted test.corrupt_bit_test_ā check error Corrupt -SET SESSION debug="-d,dict_set_index_corrupted"; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead +SET debug_dbug = @save_dbug; CREATE INDEX idx3 ON corrupt_bit_test_ā(b, c); ERROR HY000: Index idx is corrupted CREATE INDEX idx4 ON corrupt_bit_test_ā(b, z); diff --git a/mysql-test/suite/innodb/r/read_only_recovery.result b/mysql-test/suite/innodb/r/read_only_recovery.result index 97ec938fb2a..e639e8abacc 100644 --- a/mysql-test/suite/innodb/r/read_only_recovery.result +++ b/mysql-test/suite/innodb/r/read_only_recovery.result @@ -37,3 +37,4 @@ SELECT * FROM t; a 3 DROP TABLE t; +FOUND 1 /Rolled back recovered transaction [^0]/ in mysqld.1.err diff --git a/mysql-test/suite/innodb/r/update-cascade.result b/mysql-test/suite/innodb/r/update-cascade.result new file mode 100644 index 00000000000..a3c8fed931e --- /dev/null +++ b/mysql-test/suite/innodb/r/update-cascade.result @@ -0,0 +1,290 @@ +# +# Bug #18451287 REDUNDANT DELETE MARKING AFTER DB_LOCK_WAIT +# +create table t1 (f1 int primary key, f2 blob) engine=innodb; +create table t2 (f1 int primary key, f2 int, +foreign key (f2) references t1(f1) on update cascade) engine=innodb; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` blob DEFAULT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) NOT NULL, + `f2` int(11) DEFAULT NULL, + PRIMARY KEY (`f1`), + KEY `f2` (`f2`), + CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t1` (`f1`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +insert into t1 values (1, repeat('+', 20000)); +insert into t1 values (2, repeat('-', 20000)); +insert into t1 values (3, repeat('=', 20000)); +insert into t2 values (1, 2); +select f1, right(f2, 20) as p2 from t1; +f1 p2 +1 ++++++++++++++++++++ +2 -------------------- +3 ==================== +select f1, f2 from t2; +f1 f2 +1 2 +connect con1,localhost,root,,test; +start transaction; +select f1, f2 from t2 for update; +f1 f2 +1 2 +connection default; +set debug_sync='lock_wait_suspend_thread_enter SIGNAL upd_waiting WAIT_FOR go_upd'; +update t1 set f1 = 10 where f1 = 2; +connection con1; +set debug_sync='now WAIT_FOR upd_waiting'; +rollback; +set debug_sync='now SIGNAL go_upd'; +connection default; +# reap: update t1 set f1 = 10 where f1 = 2; +select f1, right(f2, 20) as p2 from t1; +f1 p2 +1 ++++++++++++++++++++ +3 ==================== +10 -------------------- +select f1, f2 from t2; +f1 f2 +1 10 +drop table t2, t1; +set debug_sync = reset; +# +# Test Scenario: Two tables t1 -> t2 are involved in update cascade. +# If DB_LOCK_WAIT happens when t1 is being updated and FK constraints +# are being checked in t2, then retry must happen on t1. The update +# cascade happens in secondary index. For secondary index testing, +# blobs are not needed. +# +create table t1 (f1 int primary key, f2 int, key k1(f2)) engine=innodb; +create table t2 (f1 int primary key, f2 int, +foreign key (f2) references t1(f2) on update cascade) engine=innodb; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` int(11) DEFAULT NULL, + PRIMARY KEY (`f1`), + KEY `k1` (`f2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) NOT NULL, + `f2` int(11) DEFAULT NULL, + PRIMARY KEY (`f1`), + KEY `f2` (`f2`), + CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t1` (`f2`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +insert into t1 values (1, 91); +insert into t2 values (1, 91); +select f1, f2 from t1; +f1 f2 +1 91 +select f1, f2 from t2; +f1 f2 +1 91 +connection con1; +start transaction; +select f1, f2 from t2 for update; +f1 f2 +1 91 +connection default; +set debug_sync='lock_wait_suspend_thread_enter SIGNAL upd_waiting WAIT_FOR go_upd'; +update t1 set f2 = 28 where f2 = 91; +connection con1; +set debug_sync='now WAIT_FOR upd_waiting'; +rollback; +set debug_sync='now SIGNAL go_upd'; +connection default; +# reap: update t1 set f1 = 10 where f1 = 2; +select f1, f2 from t1; +f1 f2 +1 28 +select f1, f2 from t2; +f1 f2 +1 28 +drop table t2, t1; +set debug_sync = reset; +# +# Test Scenario: Three tables t1 -> t2 -> t3 are involved in update cascade. +# If DB_LOCK_WAIT happens when t2 is being updated, then retry must happen +# on t2. +# +create table t1 (f1 int primary key, f2 blob) engine=innodb; +create table t2 (f1 int primary key, f2 blob, +foreign key (f1) references t1(f1) on update cascade) engine=innodb; +create table t3 (f1 int primary key, f2 blob, +foreign key (f1) references t2(f1) on update cascade) engine=innodb; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` blob DEFAULT NULL, + PRIMARY KEY (`f1`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) NOT NULL, + `f2` blob DEFAULT NULL, + PRIMARY KEY (`f1`), + CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t1` (`f1`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +show create table t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `f1` int(11) NOT NULL, + `f2` blob DEFAULT NULL, + PRIMARY KEY (`f1`), + CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`f1`) REFERENCES `t2` (`f1`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +insert into t1 values (2, repeat('-', 20000)); +insert into t2 values (2, repeat('%', 20000)); +insert into t3 values (2, repeat('+', 20000)); +select f1, right(f2, 20) as p2 from t1; +f1 p2 +2 -------------------- +select f1, right(f2, 20) as p2 from t2; +f1 p2 +2 %%%%%%%%%%%%%%%%%%%% +select f1, right(f2, 20) as p2 from t3; +f1 p2 +2 ++++++++++++++++++++ +connection con1; +start transaction; +select f1 from t3 for update; +f1 +2 +connection default; +set debug_sync='lock_wait_suspend_thread_enter SIGNAL upd_waiting WAIT_FOR go_upd'; +update t1 set f1 = 10 where f1 = 2; +connection con1; +set debug_sync='now WAIT_FOR upd_waiting'; +rollback; +# The table t1 is updated. +# In t2 delete-mark happened. Retry will happen on t2. +# In t3 yet to be updated. +set session transaction isolation level read uncommitted; +start transaction; +select f1, right(f2, 20) as p2 from t1; +f1 p2 +select f1, right(f2, 20) as p2 from t2; +f1 p2 +select f1, right(f2, 20) as p2 from t3; +f1 p2 +2 ++++++++++++++++++++ +commit; +set debug_sync='now SIGNAL go_upd'; +connection default; +# reap: update t1 set f1 = 10 where f1 = 2; +start transaction; +select f1, right(f2, 20) as p2 from t1; +f1 p2 +10 -------------------- +select f1, right(f2, 20) as p2 from t2; +f1 p2 +10 %%%%%%%%%%%%%%%%%%%% +select f1, right(f2, 20) as p2 from t3; +f1 p2 +10 ++++++++++++++++++++ +commit; +drop table t3, t2, t1; +set debug_sync = reset; +# +# Test Scenario: Three tables t1 -> t2 -> t3 are involved in update +# cascade. If DB_LOCK_WAIT happens when t2 is being updated, then +# retry must happen on t2. The update cascade is happening via +# secondary index (hence blobs are not needed). +# +create table t1 (f1 int primary key, f2 int, key k1(f2)) engine=innodb; +create table t2 (f1 int primary key, f2 int, +foreign key (f2) references t1(f2) on update cascade) engine=innodb; +create table t3 (f1 int primary key, f2 int, +foreign key (f2) references t2(f2) on update cascade) engine=innodb; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) NOT NULL, + `f2` int(11) DEFAULT NULL, + PRIMARY KEY (`f1`), + KEY `k1` (`f2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +show create table t2; +Table Create Table +t2 CREATE TABLE `t2` ( + `f1` int(11) NOT NULL, + `f2` int(11) DEFAULT NULL, + PRIMARY KEY (`f1`), + KEY `f2` (`f2`), + CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t1` (`f2`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +show create table t3; +Table Create Table +t3 CREATE TABLE `t3` ( + `f1` int(11) NOT NULL, + `f2` int(11) DEFAULT NULL, + PRIMARY KEY (`f1`), + KEY `f2` (`f2`), + CONSTRAINT `t3_ibfk_1` FOREIGN KEY (`f2`) REFERENCES `t2` (`f2`) ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +insert into t1 values (2, 91); +insert into t2 values (2, 91); +insert into t3 values (2, 91); +select f1, f2 from t1; +f1 f2 +2 91 +select f1, f2 from t2; +f1 f2 +2 91 +select f1, f2 from t3; +f1 f2 +2 91 +connection con1; +start transaction; +select f1 from t3 for update; +f1 +2 +connection default; +set debug_sync='lock_wait_suspend_thread_enter SIGNAL upd_waiting WAIT_FOR go_upd'; +update t1 set f2 = 28 where f2 = 91; +connection con1; +set debug_sync='now WAIT_FOR upd_waiting'; +rollback; +# The table t1 is updated. +# In t2 delete-mark happened. Retry will happen on t2. +# In t3 yet to be updated. +set session transaction isolation level read uncommitted; +start transaction; +select f1, f2 from t1; +f1 f2 +select f1, f2 from t2; +f1 f2 +select f1, f2 from t3; +f1 f2 +2 91 +commit; +set debug_sync='now SIGNAL go_upd'; +disconnect con1; +connection default; +# reap: update t1 set f2 = 28 where f2 = 91; +start transaction; +select f1, f2 from t1; +f1 f2 +2 28 +select f1, f2 from t2; +f1 f2 +2 28 +select f1, f2 from t3; +f1 f2 +2 28 +commit; +drop table t3, t2, t1; +set debug_sync = reset; diff --git a/mysql-test/suite/innodb/t/foreign_key.test b/mysql-test/suite/innodb/t/foreign_key.test index 3d3466c90f0..862717647b5 100644 --- a/mysql-test/suite/innodb/t/foreign_key.test +++ b/mysql-test/suite/innodb/t/foreign_key.test @@ -236,4 +236,44 @@ DELETE FROM t1 WHERE id = 1; SELECT * FROM t2; DROP TABLE t2, t1; +--echo # +--echo # MDEV-15199 Referential integrity broken in ON DELETE CASCADE +--echo # + +CREATE TABLE member (id int AUTO_INCREMENT PRIMARY KEY) ENGINE=InnoDB; +INSERT INTO member VALUES (1); +CREATE TABLE address ( + id int AUTO_INCREMENT PRIMARY KEY, + member_id int NOT NULL, + KEY address_FI_1 (member_id), + CONSTRAINT address_FK_1 FOREIGN KEY (member_id) REFERENCES member (id) + ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB; + +INSERT INTO address VALUES (2,1); +CREATE TABLE payment_method ( + id int AUTO_INCREMENT PRIMARY KEY, + member_id int NOT NULL, + cardholder_address_id int DEFAULT NULL, + KEY payment_method_FI_1 (member_id), + KEY payment_method_FI_2 (cardholder_address_id), + CONSTRAINT payment_method_FK_1 FOREIGN KEY (member_id) REFERENCES member (id) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT payment_method_FK_2 FOREIGN KEY (cardholder_address_id) REFERENCES address (id) ON DELETE SET NULL ON UPDATE CASCADE +) ENGINE=InnoDB; + +INSERT INTO payment_method VALUES (3,1,2); + +BEGIN; +UPDATE member SET id=42; +SELECT * FROM member; +SELECT * FROM address; +SELECT * FROM payment_method; +DELETE FROM member; +COMMIT; +SELECT * FROM member; +SELECT * FROM address; +SELECT * FROM payment_method; + +DROP TABLE payment_method,address,member; + --source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb/t/innodb-replace-debug.test b/mysql-test/suite/innodb/t/innodb-replace-debug.test index 5cec9e1febf..7e710ae154c 100644 --- a/mysql-test/suite/innodb/t/innodb-replace-debug.test +++ b/mysql-test/suite/innodb/t/innodb-replace-debug.test @@ -8,8 +8,9 @@ create table t1 (f1 int primary key, f2 int, f3 int, unique key k1(f2), key k2(f3)) engine=innodb; insert into t1 values (14, 24, 34); -set @@debug_dbug = '+d,row_ins_sec_index_entry_timeout'; +set @old_dbug= @@session.debug_dbug; +set debug_dbug = '+d,row_ins_sec_index_entry_timeout'; replace into t1 values (14, 25, 34); select * from t1; drop table t1; -set @@debug_dbug = '-d,row_ins_sec_index_entry_timeout'; +set debug_dbug = @old_dbug; diff --git a/mysql-test/suite/innodb/t/innodb.test b/mysql-test/suite/innodb/t/innodb.test index 05c135bfcbe..4ebd4f2fa73 100644 --- a/mysql-test/suite/innodb/t/innodb.test +++ b/mysql-test/suite/innodb/t/innodb.test @@ -5,6 +5,10 @@ let $MYSQLD_DATADIR= `select @@datadir`; let collation=utf8_unicode_ci; --source include/have_collation.inc + +create temporary table t (a char(1) character set filename) engine=innodb; +drop temporary table t; + set optimizer_switch = 'mrr=on,mrr_sort_keys=on,index_condition_pushdown=on'; # Save the original values of some variables in order to be able to @@ -1054,82 +1058,18 @@ DROP TABLE t2,t1; # # test for FK cascade depth limit # -call mtr.add_suppression("Cannot delete/update rows with cascading foreign key constraints that exceed max depth of 255. Please drop excessive foreign constraints and try again"); +call mtr.add_suppression("Cannot delete/update rows with cascading foreign key constraints that exceed max depth of 15\\. Please drop excessive foreign constraints and try again"); create table t1( id int primary key, pid int, index(pid), foreign key(pid) references t1(id) on delete cascade) engine=innodb; -insert into t1 values -( 0, 0), ( 1, 0), ( 2, 1), ( 3, 2), -( 4, 3), ( 5, 4), ( 6, 5), ( 7, 6), -( 8, 7), ( 9, 8), ( 10, 9), ( 11, 10), -( 12, 11), ( 13, 12), ( 14, 13), ( 15, 14), -( 16, 15), ( 17, 16), ( 18, 17), ( 19, 18), -( 20, 19), ( 21, 20), ( 22, 21), ( 23, 22), -( 24, 23), ( 25, 24), ( 26, 25), ( 27, 26), -( 28, 27), ( 29, 28), ( 30, 29), ( 31, 30), -( 32, 31), ( 33, 32), ( 34, 33), ( 35, 34), -( 36, 35), ( 37, 36), ( 38, 37), ( 39, 38), -( 40, 39), ( 41, 40), ( 42, 41), ( 43, 42), -( 44, 43), ( 45, 44), ( 46, 45), ( 47, 46), -( 48, 47), ( 49, 48), ( 50, 49), ( 51, 50), -( 52, 51), ( 53, 52), ( 54, 53), ( 55, 54), -( 56, 55), ( 57, 56), ( 58, 57), ( 59, 58), -( 60, 59), ( 61, 60), ( 62, 61), ( 63, 62), -( 64, 63), ( 65, 64), ( 66, 65), ( 67, 66), -( 68, 67), ( 69, 68), ( 70, 69), ( 71, 70), -( 72, 71), ( 73, 72), ( 74, 73), ( 75, 74), -( 76, 75), ( 77, 76), ( 78, 77), ( 79, 78), -( 80, 79), ( 81, 80), ( 82, 81), ( 83, 82), -( 84, 83), ( 85, 84), ( 86, 85), ( 87, 86), -( 88, 87), ( 89, 88), ( 90, 89), ( 91, 90), -( 92, 91), ( 93, 92), ( 94, 93), ( 95, 94), -( 96, 95), ( 97, 96), ( 98, 97), ( 99, 98), -(100, 99), (101, 100), (102, 101), (103, 102), -(104, 103), (105, 104), (106, 105), (107, 106), -(108, 107), (109, 108), (110, 109), (111, 110), -(112, 111), (113, 112), (114, 113), (115, 114), -(116, 115), (117, 116), (118, 117), (119, 118), -(120, 119), (121, 120), (122, 121), (123, 122), -(124, 123), (125, 124), (126, 125), (127, 126), -(128, 127), (129, 128), (130, 129), (131, 130), -(132, 131), (133, 132), (134, 133), (135, 134), -(136, 135), (137, 136), (138, 137), (139, 138), -(140, 139), (141, 140), (142, 141), (143, 142), -(144, 143), (145, 144), (146, 145), (147, 146), -(148, 147), (149, 148), (150, 149), (151, 150), -(152, 151), (153, 152), (154, 153), (155, 154), -(156, 155), (157, 156), (158, 157), (159, 158), -(160, 159), (161, 160), (162, 161), (163, 162), -(164, 163), (165, 164), (166, 165), (167, 166), -(168, 167), (169, 168), (170, 169), (171, 170), -(172, 171), (173, 172), (174, 173), (175, 174), -(176, 175), (177, 176), (178, 177), (179, 178), -(180, 179), (181, 180), (182, 181), (183, 182), -(184, 183), (185, 184), (186, 185), (187, 186), -(188, 187), (189, 188), (190, 189), (191, 190), -(192, 191), (193, 192), (194, 193), (195, 194), -(196, 195), (197, 196), (198, 197), (199, 198), -(200, 199), (201, 200), (202, 201), (203, 202), -(204, 203), (205, 204), (206, 205), (207, 206), -(208, 207), (209, 208), (210, 209), (211, 210), -(212, 211), (213, 212), (214, 213), (215, 214), -(216, 215), (217, 216), (218, 217), (219, 218), -(220, 219), (221, 220), (222, 221), (223, 222), -(224, 223), (225, 224), (226, 225), (227, 226), -(228, 227), (229, 228), (230, 229), (231, 230), -(232, 231), (233, 232), (234, 233), (235, 234), -(236, 235), (237, 236), (238, 237), (239, 238), -(240, 239), (241, 240), (242, 241), (243, 242), -(244, 243), (245, 244), (246, 245), (247, 246), -(248, 247), (249, 248), (250, 249), (251, 250), -(252, 251), (253, 252), (254, 253), (255, 254); +insert into t1 values(0,0),(1,0),(2,1),(3,2),(4,3),(5,4),(6,5),(7,6), +(8,7),(9,8),(10,9),(11,10),(12,11),(13,12),(14,13),(15,14); --error ER_GET_ERRMSG,ER_ROW_IS_REFERENCED_2 delete from t1 where id=0; -delete from t1 where id=255; ---error 0,ER_ROW_IS_REFERENCED_2 +delete from t1 where id=15; delete from t1 where id=0; drop table t1; @@ -2688,17 +2628,3 @@ SELECT * FROM t2; DROP TABLE t1; DROP TABLE t2; -####################################################################### -# # -# Please, DO NOT TOUCH this file as well as the innodb.result file. # -# These files are to be modified ONLY BY INNOBASE guys. # -# # -# Use innodb_mysql.[test|result] files instead. # -# # -# If nevertheless you need to make some changes here, please, forward # -# your commit message # -# To: innodb_dev_ww@oracle.com # -# Cc: dev-innodb@mysql.com # -# (otherwise your changes may be erased). # -# # -####################################################################### diff --git a/mysql-test/suite/innodb/t/innodb_buffer_pool_resize.opt b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize.opt new file mode 100644 index 00000000000..39543543a53 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize.opt @@ -0,0 +1,2 @@ +--innodb-buffer-pool-size=8M +--innodb-page-size=4k diff --git a/mysql-test/suite/innodb/t/innodb_buffer_pool_resize.test b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize.test new file mode 100644 index 00000000000..77fdb49a57d --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize.test @@ -0,0 +1,74 @@ +# +# WL6117 : Resize the InnoDB Buffer Pool Online +# + +--source include/have_innodb.inc +--source include/big_test.inc + +let $wait_timeout = 180; +let $wait_condition = + SELECT SUBSTR(variable_value, 1, 34) = 'Completed resizing buffer pool at ' + FROM information_schema.global_status + WHERE LOWER(variable_name) = 'innodb_buffer_pool_resize_status'; + +--disable_query_log +set @old_innodb_buffer_pool_size = @@innodb_buffer_pool_size; +set @old_innodb_adaptive_hash_index = @@innodb_adaptive_hash_index; +if (`select (version() like '%debug%') > 0`) +{ + set @old_innodb_disable_resize = @@innodb_disable_resize_buffer_pool_debug; + set global innodb_disable_resize_buffer_pool_debug = OFF; +} +--enable_query_log + +set global innodb_adaptive_hash_index=ON; + +select @@innodb_buffer_pool_size; + +# Expand buffer pool +set global innodb_buffer_pool_size = 10485760; + +--source include/wait_condition.inc + +select @@innodb_buffer_pool_size; + +# fill buffer pool +create table t1 (id int not null, val int not null default '0', primary key (id)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +create or replace view view0 as select 1 union all select 1; + +set @`v_id` := 0; +set @`v_val` := 0; + +# 2^18 == 262144 records +replace into t1 select (@`v_id` := (@`v_id` + 4) mod 4294967296) as id, (@`v_val` := (@`v_val` + 4) mod 4294967296) as val from view0 v0, view0 v1, view0 v2, view0 v3, view0 v4, view0 v5, view0 v6, view0 v7, view0 v8, view0 v9, view0 v10, view0 v11, view0 v12, view0 v13, view0 v14, view0 v15, view0 v16, view0 v17; + +# Shrink buffer pool +set global innodb_buffer_pool_size = 7340032; +--source include/wait_condition.inc + +select @@innodb_buffer_pool_size; + +select count(val) from t1; + +set global innodb_adaptive_hash_index=OFF; + +# Expand buffer pool to 24MB +set global innodb_buffer_pool_size = 25165824; +--source include/wait_condition.inc + +select @@innodb_buffer_pool_size; + +select count(val) from t1; + +drop table t1; +drop view view0; + +--disable_query_log +set global innodb_adaptive_hash_index = @old_innodb_adaptive_hash_index; +set global innodb_buffer_pool_size = @old_innodb_buffer_pool_size; +if (`select (version() like '%debug%') > 0`) +{ + set global innodb_disable_resize_buffer_pool_debug = @old_innodb_disable_resize; +} +--enable_query_log +--source include/wait_condition.inc diff --git a/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_with_chunks.opt b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_with_chunks.opt new file mode 100644 index 00000000000..b97a3995457 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_with_chunks.opt @@ -0,0 +1,3 @@ +--innodb-buffer-pool-size=16M +--innodb-buffer-pool-chunk-size=2M +--innodb-page-size=4k diff --git a/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_with_chunks.test b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_with_chunks.test new file mode 100644 index 00000000000..b04b0306bf1 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_buffer_pool_resize_with_chunks.test @@ -0,0 +1,63 @@ +# +# WL6117 : Resize the InnoDB Buffer Pool Online +# (innodb_buffer_pool_chunk_size used case) +# + +--source include/have_innodb.inc +--source include/big_test.inc + +let $wait_timeout = 180; +let $wait_condition = + SELECT SUBSTR(variable_value, 1, 34) = 'Completed resizing buffer pool at ' + FROM information_schema.global_status + WHERE LOWER(variable_name) = 'innodb_buffer_pool_resize_status'; + +--disable_query_log +set @old_innodb_buffer_pool_size = @@innodb_buffer_pool_size; +if (`select (version() like '%debug%') > 0`) +{ + set @old_innodb_disable_resize = @@innodb_disable_resize_buffer_pool_debug; + set global innodb_disable_resize_buffer_pool_debug = OFF; +} +--enable_query_log + +select @@innodb_buffer_pool_chunk_size; + +# fill buffer pool +create table t1 (id int not null, val int not null default '0', primary key (id)) ENGINE=InnoDB ROW_FORMAT=COMPRESSED; +create or replace view view0 as select 1 union all select 1; + +set @`v_id` := 0; +set @`v_val` := 0; + +# 2^18 == 262144 records +replace into t1 select (@`v_id` := (@`v_id` + 4) mod 4294967296) as id, (@`v_val` := (@`v_val` + 4) mod 4294967296) as val from view0 v0, view0 v1, view0 v2, view0 v3, view0 v4, view0 v5, view0 v6, view0 v7, view0 v8, view0 v9, view0 v10, view0 v11, view0 v12, view0 v13, view0 v14, view0 v15, view0 v16, view0 v17; + +# Shrink buffer pool to 7MB +set global innodb_buffer_pool_size = 7340032; +--source include/wait_condition.inc + +select count(val) from t1; + +# Expand buffer pool to 16MB +set global innodb_buffer_pool_size = 16777216; +--source include/wait_condition.inc + +select count(val) from t1; + +drop table t1; +drop view view0; + +# Try to shrink buffer pool to smaller than chunk size +set global innodb_buffer_pool_size = 1048576; +--source include/wait_condition.inc +select @@innodb_buffer_pool_size; + +--disable_query_log +set global innodb_buffer_pool_size = @old_innodb_buffer_pool_size; +if (`select (version() like '%debug%') > 0`) +{ + set global innodb_disable_resize_buffer_pool_debug = @old_innodb_disable_resize; +} +--enable_query_log +--source include/wait_condition.inc diff --git a/mysql-test/suite/innodb/t/innodb_corrupt_bit.test b/mysql-test/suite/innodb/t/innodb_corrupt_bit.test index 52a318f0fa8..1d723c0bbc3 100644 --- a/mysql-test/suite/innodb/t/innodb_corrupt_bit.test +++ b/mysql-test/suite/innodb/t/innodb_corrupt_bit.test @@ -33,9 +33,10 @@ INSERT INTO corrupt_bit_test_ā SELECT 0,b,c+1,z+1 FROM corrupt_bit_test_ā; select count(*) from corrupt_bit_test_ā; # This will flag all secondary indexes corrupted -SET SESSION debug="+d,dict_set_index_corrupted"; +SET @save_dbug = @@SESSION.debug_dbug; +SET debug_dbug = '+d,dict_set_index_corrupted'; check table corrupt_bit_test_ā; -SET SESSION debug="-d,dict_set_index_corrupted"; +SET debug_dbug = @save_dbug; # Cannot create new indexes while corrupted indexes exist --error ER_INDEX_CORRUPT diff --git a/mysql-test/suite/innodb/t/log_file_size.test b/mysql-test/suite/innodb/t/log_file_size.test index 140198de4ab..44cb155c7d9 100644 --- a/mysql-test/suite/innodb/t/log_file_size.test +++ b/mysql-test/suite/innodb/t/log_file_size.test @@ -17,7 +17,8 @@ call mtr.add_suppression("Plugin 'InnoDB' registration as a STORAGE ENGINE faile call mtr.add_suppression("InnoDB: Plugin initialization aborted"); call mtr.add_suppression("InnoDB: innodb_read_only prevents crash recovery"); call mtr.add_suppression("InnoDB: Are you sure you are using the right ib_logfiles"); -call mtr.add_suppression("InnoDB: Cannot create log files in read-only mode"); +call mtr.add_suppression("InnoDB: Cannot (create|resize) log files in read-only mode"); +call mtr.add_suppression("InnoDB: Can't initiate database recovery, running in read-only-mode"); call mtr.add_suppression("InnoDB: Only one log file found"); call mtr.add_suppression("InnoDB: Log file .*ib_logfile[01].* size"); call mtr.add_suppression("InnoDB: Unable to open .*ib_logfile0. to check native AIO read support"); diff --git a/mysql-test/suite/innodb/t/read_only_recovery.test b/mysql-test/suite/innodb/t/read_only_recovery.test index aea676d3644..7da012efb74 100644 --- a/mysql-test/suite/innodb/t/read_only_recovery.test +++ b/mysql-test/suite/innodb/t/read_only_recovery.test @@ -41,3 +41,6 @@ SELECT * FROM t; --source include/restart_mysqld.inc SELECT * FROM t; DROP TABLE t; +let SEARCH_FILE= $MYSQLTEST_VARDIR/log/mysqld.1.err; +--let SEARCH_PATTERN= Rolled back recovered transaction [^0] +--source include/search_pattern_in_file.inc diff --git a/mysql-test/suite/innodb/t/table_definition_cache_debug.opt b/mysql-test/suite/innodb/t/table_definition_cache_debug.opt index 6d341857397..c2db7e1df6e 100644 --- a/mysql-test/suite/innodb/t/table_definition_cache_debug.opt +++ b/mysql-test/suite/innodb/t/table_definition_cache_debug.opt @@ -1 +1 @@ ---innodb-open-files=20 +--innodb-open-files=30 diff --git a/mysql-test/suite/innodb/t/update-cascade.test b/mysql-test/suite/innodb/t/update-cascade.test new file mode 100644 index 00000000000..de8294703b4 --- /dev/null +++ b/mysql-test/suite/innodb/t/update-cascade.test @@ -0,0 +1,221 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +# Save the initial number of concurrent sessions +--source include/count_sessions.inc + +--echo # +--echo # Bug #18451287 REDUNDANT DELETE MARKING AFTER DB_LOCK_WAIT +--echo # + +create table t1 (f1 int primary key, f2 blob) engine=innodb; +create table t2 (f1 int primary key, f2 int, + foreign key (f2) references t1(f1) on update cascade) engine=innodb; + +show create table t1; +show create table t2; +insert into t1 values (1, repeat('+', 20000)); +insert into t1 values (2, repeat('-', 20000)); +insert into t1 values (3, repeat('=', 20000)); +insert into t2 values (1, 2); + +select f1, right(f2, 20) as p2 from t1; +select f1, f2 from t2; + +connect(con1,localhost,root,,test); +start transaction; +select f1, f2 from t2 for update; + +connection default; +set debug_sync='lock_wait_suspend_thread_enter SIGNAL upd_waiting WAIT_FOR go_upd'; +send update t1 set f1 = 10 where f1 = 2; + +connection con1; +set debug_sync='now WAIT_FOR upd_waiting'; +rollback; +set debug_sync='now SIGNAL go_upd'; + +connection default; +--echo # reap: update t1 set f1 = 10 where f1 = 2; +reap; + +select f1, right(f2, 20) as p2 from t1; +select f1, f2 from t2; + +drop table t2, t1; + +set debug_sync = reset; + +--echo # +--echo # Test Scenario: Two tables t1 -> t2 are involved in update cascade. +--echo # If DB_LOCK_WAIT happens when t1 is being updated and FK constraints +--echo # are being checked in t2, then retry must happen on t1. The update +--echo # cascade happens in secondary index. For secondary index testing, +--echo # blobs are not needed. +--echo # + +create table t1 (f1 int primary key, f2 int, key k1(f2)) engine=innodb; +create table t2 (f1 int primary key, f2 int, + foreign key (f2) references t1(f2) on update cascade) engine=innodb; + +show create table t1; +show create table t2; +insert into t1 values (1, 91); +insert into t2 values (1, 91); + +select f1, f2 from t1; +select f1, f2 from t2; + +connection con1; +start transaction; +select f1, f2 from t2 for update; + +connection default; +set debug_sync='lock_wait_suspend_thread_enter SIGNAL upd_waiting WAIT_FOR go_upd'; +send update t1 set f2 = 28 where f2 = 91; + +connection con1; +set debug_sync='now WAIT_FOR upd_waiting'; +rollback; +set debug_sync='now SIGNAL go_upd'; + +connection default; +--echo # reap: update t1 set f1 = 10 where f1 = 2; +--reap + +select f1, f2 from t1; +select f1, f2 from t2; + +drop table t2, t1; + +set debug_sync = reset; + +--echo # +--echo # Test Scenario: Three tables t1 -> t2 -> t3 are involved in update cascade. +--echo # If DB_LOCK_WAIT happens when t2 is being updated, then retry must happen +--echo # on t2. +--echo # + +create table t1 (f1 int primary key, f2 blob) engine=innodb; +create table t2 (f1 int primary key, f2 blob, + foreign key (f1) references t1(f1) on update cascade) engine=innodb; +create table t3 (f1 int primary key, f2 blob, + foreign key (f1) references t2(f1) on update cascade) engine=innodb; + +show create table t1; +show create table t2; +show create table t3; + +insert into t1 values (2, repeat('-', 20000)); +insert into t2 values (2, repeat('%', 20000)); +insert into t3 values (2, repeat('+', 20000)); + +select f1, right(f2, 20) as p2 from t1; +select f1, right(f2, 20) as p2 from t2; +select f1, right(f2, 20) as p2 from t3; + +connection con1; +start transaction; +select f1 from t3 for update; + +connection default; +set debug_sync='lock_wait_suspend_thread_enter SIGNAL upd_waiting WAIT_FOR go_upd'; +send update t1 set f1 = 10 where f1 = 2; + +connection con1; +set debug_sync='now WAIT_FOR upd_waiting'; +rollback; + +--echo # The table t1 is updated. +--echo # In t2 delete-mark happened. Retry will happen on t2. +--echo # In t3 yet to be updated. +set session transaction isolation level read uncommitted; +start transaction; +select f1, right(f2, 20) as p2 from t1; +select f1, right(f2, 20) as p2 from t2; +select f1, right(f2, 20) as p2 from t3; +commit; + +set debug_sync='now SIGNAL go_upd'; + +connection default; +--echo # reap: update t1 set f1 = 10 where f1 = 2; +--reap; + +start transaction; +select f1, right(f2, 20) as p2 from t1; +select f1, right(f2, 20) as p2 from t2; +select f1, right(f2, 20) as p2 from t3; +commit; + +drop table t3, t2, t1; + +set debug_sync = reset; + +--echo # +--echo # Test Scenario: Three tables t1 -> t2 -> t3 are involved in update +--echo # cascade. If DB_LOCK_WAIT happens when t2 is being updated, then +--echo # retry must happen on t2. The update cascade is happening via +--echo # secondary index (hence blobs are not needed). +--echo # + +create table t1 (f1 int primary key, f2 int, key k1(f2)) engine=innodb; +create table t2 (f1 int primary key, f2 int, + foreign key (f2) references t1(f2) on update cascade) engine=innodb; +create table t3 (f1 int primary key, f2 int, + foreign key (f2) references t2(f2) on update cascade) engine=innodb; + +show create table t1; +show create table t2; +show create table t3; + +insert into t1 values (2, 91); +insert into t2 values (2, 91); +insert into t3 values (2, 91); + +select f1, f2 from t1; +select f1, f2 from t2; +select f1, f2 from t3; + +connection con1; +start transaction; +select f1 from t3 for update; + +connection default; +set debug_sync='lock_wait_suspend_thread_enter SIGNAL upd_waiting WAIT_FOR go_upd'; +send update t1 set f2 = 28 where f2 = 91; + +connection con1; +set debug_sync='now WAIT_FOR upd_waiting'; +rollback; + +--echo # The table t1 is updated. +--echo # In t2 delete-mark happened. Retry will happen on t2. +--echo # In t3 yet to be updated. +set session transaction isolation level read uncommitted; +start transaction; +select f1, f2 from t1; +select f1, f2 from t2; +select f1, f2 from t3; +commit; + +set debug_sync='now SIGNAL go_upd'; +disconnect con1; + +connection default; +--echo # reap: update t1 set f2 = 28 where f2 = 91; +--reap; + +start transaction; +select f1, f2 from t1; +select f1, f2 from t2; +select f1, f2 from t3; +commit; + +drop table t3, t2, t1; + +set debug_sync = reset; + +# Wait till all disconnects are completed +--source include/wait_until_count_sessions.inc diff --git a/mysql-test/suite/innodb_gis/r/geometry.result b/mysql-test/suite/innodb_gis/r/geometry.result index 60c5f80f69b..780efc11bce 100644 --- a/mysql-test/suite/innodb_gis/r/geometry.result +++ b/mysql-test/suite/innodb_gis/r/geometry.result @@ -1,21 +1,5 @@ SET default_storage_engine=InnoDB; SET innodb_strict_mode=OFF; -SET SESSION debug="+d,row_print_geometry_data"; -SHOW VARIABLES LIKE '%engine%'; -Variable_name Value -default_storage_engine InnoDB -default_tmp_storage_engine InnoDB -disabled_storage_engines -internal_tmp_disk_storage_engine InnoDB -USE test; -DROP TABLE IF EXISTS t1, gis_point, gis_line, gis_polygon; -DROP TABLE IF EXISTS gis_multi_point, gis_multi_line, gis_multi_polygon; -DROP TABLE IF EXISTS gis_geometrycollection, gis_geometry; -DROP TABLE IF EXISTS tab,tab2,tab3,parent,emp2; -DROP PROCEDURE IF EXISTS geominout; -DROP PROCEDURE IF EXISTS geom_insert; -DROP TRIGGER IF EXISTS geom_trigger; -DROP PROCEDURE IF EXISTS geom_cursor; CREATE TABLE gis_point (fid INTEGER NOT NULL PRIMARY KEY, g POINT) ENGINE=InnoDB; CREATE TABLE gis_line (fid INTEGER NOT NULL PRIMARY KEY, g LINESTRING) ENGINE=InnoDB; CREATE TABLE gis_polygon (fid INTEGER NOT NULL PRIMARY KEY, g POLYGON) ENGINE=InnoDB; @@ -1136,15 +1120,10 @@ COMMIT; SELECT COUNT(*) FROM tab3; COUNT(*) 0 -DROP TABLE IF EXISTS gis_point, gis_line, gis_polygon, gis_multi_point; -DROP TABLE IF EXISTS gis_multi_line, gis_multi_polygon; -DROP TABLE IF EXISTS gis_geometrycollection, gis_geometry; -DROP TABLE IF EXISTS tab,tab2,tab3,parent,emp2; -Warnings: -Note 1051 Unknown table 'test.emp2' -DROP PROCEDURE IF EXISTS geominout; -DROP PROCEDURE IF EXISTS geom_insert; -DROP TRIGGER IF EXISTS geom_trigger; -Warnings: -Note 1360 Trigger does not exist -DROP PROCEDURE IF EXISTS geom_cursor; +DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point; +DROP TABLE gis_multi_line, gis_multi_polygon; +DROP TABLE gis_geometrycollection, gis_geometry; +DROP TABLE tab,tab2,tab3,parent; +DROP PROCEDURE geominout; +DROP PROCEDURE geom_insert; +DROP PROCEDURE geom_cursor; diff --git a/mysql-test/suite/innodb_gis/r/types.result b/mysql-test/suite/innodb_gis/r/types.result index 7d823927df1..12e1eb44cd7 100644 --- a/mysql-test/suite/innodb_gis/r/types.result +++ b/mysql-test/suite/innodb_gis/r/types.result @@ -1,6 +1,3 @@ -SET SESSION debug="+d,row_print_geometry_data"; -Warnings: -Warning 1287 '@@debug' is deprecated and will be removed in a future release. Please use '@@debug_dbug' instead CREATE TABLE t_wl6455 ( i INT, g GEOMETRY NOT NULL) ENGINE=InnoDB; SHOW CREATE TABLE t_wl6455; Table Create Table diff --git a/mysql-test/suite/innodb_gis/t/geometry.test b/mysql-test/suite/innodb_gis/t/geometry.test index 6450e82e2e4..2d030f90dc9 100644 --- a/mysql-test/suite/innodb_gis/t/geometry.test +++ b/mysql-test/suite/innodb_gis/t/geometry.test @@ -9,37 +9,15 @@ # All Geometric functions. #******************************************************** --source include/have_geometry.inc ---source include/not_embedded.inc ---source include/have_debug.inc --source include/have_innodb.inc SET default_storage_engine=InnoDB; SET innodb_strict_mode=OFF; -# Turn on the geometry data print. -SET SESSION debug="+d,row_print_geometry_data"; - -SHOW VARIABLES LIKE '%engine%'; - # # Spatial objects # -USE test; - ---disable_warnings -DROP TABLE IF EXISTS t1, gis_point, gis_line, gis_polygon; -DROP TABLE IF EXISTS gis_multi_point, gis_multi_line, gis_multi_polygon; -DROP TABLE IF EXISTS gis_geometrycollection, gis_geometry; -DROP TABLE IF EXISTS tab,tab2,tab3,parent,emp2; -DROP PROCEDURE IF EXISTS geominout; -DROP PROCEDURE IF EXISTS geom_insert; -DROP TRIGGER IF EXISTS geom_trigger; -DROP PROCEDURE IF EXISTS geom_cursor; - - ---enable_warnings - CREATE TABLE gis_point (fid INTEGER NOT NULL PRIMARY KEY, g POINT) ENGINE=InnoDB; CREATE TABLE gis_line (fid INTEGER NOT NULL PRIMARY KEY, g LINESTRING) ENGINE=InnoDB; CREATE TABLE gis_polygon (fid INTEGER NOT NULL PRIMARY KEY, g POLYGON) ENGINE=InnoDB; @@ -694,11 +672,10 @@ COMMIT; SELECT COUNT(*) FROM tab3; -DROP TABLE IF EXISTS gis_point, gis_line, gis_polygon, gis_multi_point; -DROP TABLE IF EXISTS gis_multi_line, gis_multi_polygon; -DROP TABLE IF EXISTS gis_geometrycollection, gis_geometry; -DROP TABLE IF EXISTS tab,tab2,tab3,parent,emp2; -DROP PROCEDURE IF EXISTS geominout; -DROP PROCEDURE IF EXISTS geom_insert; -DROP TRIGGER IF EXISTS geom_trigger; -DROP PROCEDURE IF EXISTS geom_cursor; +DROP TABLE gis_point, gis_line, gis_polygon, gis_multi_point; +DROP TABLE gis_multi_line, gis_multi_polygon; +DROP TABLE gis_geometrycollection, gis_geometry; +DROP TABLE tab,tab2,tab3,parent,emp2; +DROP PROCEDURE geominout; +DROP PROCEDURE geom_insert; +DROP PROCEDURE geom_cursor; diff --git a/mysql-test/suite/innodb_gis/t/types.test b/mysql-test/suite/innodb_gis/t/types.test index 65f65e5ae1f..fab0db5f755 100644 --- a/mysql-test/suite/innodb_gis/t/types.test +++ b/mysql-test/suite/innodb_gis/t/types.test @@ -6,13 +6,6 @@ # Restarting is not supported in embedded --source include/not_embedded.inc --source include/have_innodb.inc ---source include/have_debug.inc - -# Avoid CrashReporter popup on Mac ---source include/not_crashrep.inc - -# Turn on the geometry data print. -SET SESSION debug="+d,row_print_geometry_data"; # Test GEOMETRY datatype. CREATE TABLE t_wl6455 ( i INT, g GEOMETRY NOT NULL) ENGINE=InnoDB; diff --git a/mysql-test/suite/maria/lock.result b/mysql-test/suite/maria/lock.result index 52e83eb111d..90250568ef5 100644 --- a/mysql-test/suite/maria/lock.result +++ b/mysql-test/suite/maria/lock.result @@ -30,3 +30,72 @@ drop table t1; CREATE TABLE t1 (i INT) ENGINE=Aria; LOCK TABLES t1 WRITE, t1 AS t1a WRITE; DROP TABLE t1; +# +# MDEV-8200 aria bug with insert select when select is a aria table +# (wrong result or assertion failure: +# `table->file->stats.records > 0 || error') +# +CREATE TABLE t1 (f1 INT) ENGINE=Aria; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 +INSERT INTO t1 VALUES (1); +CREATE TABLE t2 (f2 INT) ENGINE=MyISAM; +CREATE TABLE tmp (f3 INT) engine=Aria; +LOCK TABLE t2 WRITE, tmp WRITE, tmp AS tmp_alias WRITE, t1 WRITE; +INSERT INTO tmp SELECT f1 FROM t1; +INSERT INTO t2 SELECT f3 FROM tmp AS tmp_alias; +select * from t2; +f2 +1 +unlock tables; +DROP TABLE t1,t2,tmp; +# +# Same without transactional +# +CREATE TABLE t1 (f1 INT) transactional=0 ENGINE=Aria; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL +) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 TRANSACTIONAL=0 +INSERT INTO t1 VALUES (2); +CREATE TABLE t2 (f2 INT) ENGINE=MyISAM; +CREATE TABLE tmp (f3 INT) transactional=0 engine=Aria; +LOCK TABLE t2 WRITE, tmp WRITE, tmp AS tmp_alias WRITE, t1 WRITE; +INSERT INTO tmp SELECT f1 FROM t1; +INSERT INTO t2 SELECT f3 FROM tmp AS tmp_alias; +select * from t2; +f2 +2 +unlock tables; +DROP TABLE t1,t2,tmp; +# +# Using spatical keys (disables versioning) +# +CREATE TABLE t1 (f1 INT, c1 geometry NOT NULL, SPATIAL KEY i1 (c1)) transactional=1 ENGINE=Aria; +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `f1` int(11) DEFAULT NULL, + `c1` geometry NOT NULL, + SPATIAL KEY `i1` (`c1`) +) ENGINE=Aria DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 TRANSACTIONAL=1 +INSERT INTO t1 VALUES (3, +PolygonFromText('POLYGON((-18.6086111000 -66.9327777000, + -18.6055555000 -66.8158332999, + -18.7186111000 -66.8102777000, + -18.7211111000 -66.9269443999, + -18.6086111000 -66.9327777000))')); +CREATE TABLE t2 (f2 INT) ENGINE=MyISAM; +CREATE TABLE tmp (f3 INT, c1 geometry NOT NULL, SPATIAL KEY i1 (c1)) transactional=1 ENGINE=Aria; +LOCK TABLE t2 WRITE, tmp WRITE, tmp AS tmp_alias WRITE, t1 WRITE; +INSERT INTO tmp SELECT f1,c1 FROM t1; +INSERT INTO t2 (f2) SELECT f3 FROM tmp AS tmp_alias; +select * from t2; +f2 +3 +unlock tables; +DROP TABLE t1,t2,tmp; diff --git a/mysql-test/suite/maria/lock.test b/mysql-test/suite/maria/lock.test index 5b6d17069e7..57447a18c55 100644 --- a/mysql-test/suite/maria/lock.test +++ b/mysql-test/suite/maria/lock.test @@ -50,3 +50,58 @@ drop table t1; CREATE TABLE t1 (i INT) ENGINE=Aria; LOCK TABLES t1 WRITE, t1 AS t1a WRITE; DROP TABLE t1; + +--echo # +--echo # MDEV-8200 aria bug with insert select when select is a aria table +--echo # (wrong result or assertion failure: +--echo # `table->file->stats.records > 0 || error') +--echo # + +CREATE TABLE t1 (f1 INT) ENGINE=Aria; +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (1); +CREATE TABLE t2 (f2 INT) ENGINE=MyISAM; +CREATE TABLE tmp (f3 INT) engine=Aria; +LOCK TABLE t2 WRITE, tmp WRITE, tmp AS tmp_alias WRITE, t1 WRITE; +INSERT INTO tmp SELECT f1 FROM t1; +INSERT INTO t2 SELECT f3 FROM tmp AS tmp_alias; +select * from t2; +unlock tables; +DROP TABLE t1,t2,tmp; + +--echo # +--echo # Same without transactional +--echo # + +CREATE TABLE t1 (f1 INT) transactional=0 ENGINE=Aria; +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (2); +CREATE TABLE t2 (f2 INT) ENGINE=MyISAM; +CREATE TABLE tmp (f3 INT) transactional=0 engine=Aria; +LOCK TABLE t2 WRITE, tmp WRITE, tmp AS tmp_alias WRITE, t1 WRITE; +INSERT INTO tmp SELECT f1 FROM t1; +INSERT INTO t2 SELECT f3 FROM tmp AS tmp_alias; +select * from t2; +unlock tables; +DROP TABLE t1,t2,tmp; + +--echo # +--echo # Using spatical keys (disables versioning) +--echo # + +CREATE TABLE t1 (f1 INT, c1 geometry NOT NULL, SPATIAL KEY i1 (c1)) transactional=1 ENGINE=Aria; +SHOW CREATE TABLE t1; +INSERT INTO t1 VALUES (3, +PolygonFromText('POLYGON((-18.6086111000 -66.9327777000, + -18.6055555000 -66.8158332999, + -18.7186111000 -66.8102777000, + -18.7211111000 -66.9269443999, + -18.6086111000 -66.9327777000))')); +CREATE TABLE t2 (f2 INT) ENGINE=MyISAM; +CREATE TABLE tmp (f3 INT, c1 geometry NOT NULL, SPATIAL KEY i1 (c1)) transactional=1 ENGINE=Aria; +LOCK TABLE t2 WRITE, tmp WRITE, tmp AS tmp_alias WRITE, t1 WRITE; +INSERT INTO tmp SELECT f1,c1 FROM t1; +INSERT INTO t2 (f2) SELECT f3 FROM tmp AS tmp_alias; +select * from t2; +unlock tables; +DROP TABLE t1,t2,tmp; diff --git a/mysql-test/suite/maria/maria.result b/mysql-test/suite/maria/maria.result index c7a08c4d95e..32c7af632c7 100644 --- a/mysql-test/suite/maria/maria.result +++ b/mysql-test/suite/maria/maria.result @@ -2734,6 +2734,17 @@ count(*) 13 drop table t1; # +# MDEV-14690: Assertion `page_link == &fake_link' failed in +# pagecache_write_part +# +CREATE TABLE t1 (a CHAR(8), b CHAR(8), c CHAR(8) NOT NULL DEFAULT '', f FLOAT, KEY(f)) ENGINE=Aria; +INSERT INTO t1 (a) VALUES ('foo'); +DELETE FROM t1 WHERE c < 'bar'; +ALTER TABLE t1 DISABLE KEYS; +INSERT INTO t1 (b) VALUES (''); +ALTER TABLE t1 ENABLE KEYS; +DROP TABLE t1; +# # BUG#47444 - --myisam_repair_threads > 1 can result in all index # cardinalities=1 # diff --git a/mysql-test/suite/maria/maria.test b/mysql-test/suite/maria/maria.test index 24b97577d5e..79cd3fe3ad9 100644 --- a/mysql-test/suite/maria/maria.test +++ b/mysql-test/suite/maria/maria.test @@ -1975,6 +1975,21 @@ select count(*) from t1; drop table t1; --echo # +--echo # MDEV-14690: Assertion `page_link == &fake_link' failed in +--echo # pagecache_write_part +--echo # + +CREATE TABLE t1 (a CHAR(8), b CHAR(8), c CHAR(8) NOT NULL DEFAULT '', f FLOAT, KEY(f)) ENGINE=Aria; +INSERT INTO t1 (a) VALUES ('foo'); +DELETE FROM t1 WHERE c < 'bar'; +ALTER TABLE t1 DISABLE KEYS; +INSERT INTO t1 (b) VALUES (''); +ALTER TABLE t1 ENABLE KEYS; + +# Cleanup +DROP TABLE t1; + +--echo # --echo # BUG#47444 - --myisam_repair_threads > 1 can result in all index --echo # cardinalities=1 --echo # diff --git a/mysql-test/suite/maria/repair.result b/mysql-test/suite/maria/repair.result new file mode 100644 index 00000000000..6bb9e1b5b9e --- /dev/null +++ b/mysql-test/suite/maria/repair.result @@ -0,0 +1,24 @@ +CREATE TABLE t1 (i INT) ENGINE=Aria TRANSACTIONAL=1; +INSERT t1 VALUES (1); +LOCK TABLE t1 WRITE; +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +SELECT * FROM INFORMATION_SCHEMA.TABLES; +SELECT * FROM t1; +i +1 +UNLOCK TABLES; +DROP TABLE t1; +CREATE TABLE t1 (i INT) ENGINE=Aria TRANSACTIONAL=1; +INSERT t1 VALUES (1); +LOCK TABLE t1 WRITE; +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize status OK +SELECT * FROM INFORMATION_SCHEMA.TABLES; +SELECT * FROM t1; +i +1 +UNLOCK TABLES; +DROP TABLE t1; diff --git a/mysql-test/suite/maria/repair.test b/mysql-test/suite/maria/repair.test new file mode 100644 index 00000000000..2f713950d3e --- /dev/null +++ b/mysql-test/suite/maria/repair.test @@ -0,0 +1,24 @@ +# +# MDEV-11539 test_if_reopen: Assertion `strcmp(share->unique_file_name,filename) || share->last_version' failed upon select from I_S +# +CREATE TABLE t1 (i INT) ENGINE=Aria TRANSACTIONAL=1; +INSERT t1 VALUES (1); +LOCK TABLE t1 WRITE; +REPAIR TABLE t1; +--disable_result_log +SELECT * FROM INFORMATION_SCHEMA.TABLES; +--enable_result_log +SELECT * FROM t1; +UNLOCK TABLES; +DROP TABLE t1; + +CREATE TABLE t1 (i INT) ENGINE=Aria TRANSACTIONAL=1; +INSERT t1 VALUES (1); +LOCK TABLE t1 WRITE; +OPTIMIZE TABLE t1; +--disable_result_log +SELECT * FROM INFORMATION_SCHEMA.TABLES; +--enable_result_log +SELECT * FROM t1; +UNLOCK TABLES; +DROP TABLE t1; diff --git a/mysql-test/suite/mariabackup/apply-log-only-incr.result b/mysql-test/suite/mariabackup/apply-log-only-incr.result index 114a471aa2c..917a9647511 100644 --- a/mysql-test/suite/mariabackup/apply-log-only-incr.result +++ b/mysql-test/suite/mariabackup/apply-log-only-incr.result @@ -10,9 +10,9 @@ SET GLOBAL innodb_flush_log_at_trx_commit = 1; ROLLBACK; disconnect flush_log; connection default; -NOT FOUND /Rollback of trx with id/ in current_test +NOT FOUND /Rolled back recovered transaction/ in current_test # expect NOT FOUND -NOT FOUND /Rollback of trx with id/ in current_test +NOT FOUND /Rolled back recovered transaction/ in current_test # expect NOT FOUND commit; SELECT count(*) FROM t; diff --git a/mysql-test/suite/mariabackup/apply-log-only-incr.test b/mysql-test/suite/mariabackup/apply-log-only-incr.test index 81c91d3c452..25cb3a82023 100644 --- a/mysql-test/suite/mariabackup/apply-log-only-incr.test +++ b/mysql-test/suite/mariabackup/apply-log-only-incr.test @@ -40,7 +40,7 @@ exec $XTRABACKUP --prepare --apply-log-only --target-dir=$basedir ; --enable_result_log let SEARCH_FILE=$MYSQLTEST_VARDIR/log/current_test; ---let SEARCH_PATTERN= Rollback of trx with id +--let SEARCH_PATTERN= Rolled back recovered transaction --source include/search_pattern_in_file.inc --echo # expect NOT FOUND diff --git a/mysql-test/suite/mariabackup/apply-log-only.result b/mysql-test/suite/mariabackup/apply-log-only.result index 04b9c0d8ee2..d618a7bbeb5 100644 --- a/mysql-test/suite/mariabackup/apply-log-only.result +++ b/mysql-test/suite/mariabackup/apply-log-only.result @@ -2,7 +2,7 @@ call mtr.add_suppression("InnoDB: New log files created"); CREATE TABLE t(a varchar(60)) ENGINE INNODB; start transaction; INSERT INTO t VALUES(1); -NOT FOUND /Rollback of trx with id/ in current_test +NOT FOUND /Rolled back recovered transaction/ in current_test # expect NOT FOUND SELECT count(*) FROM t; count(*) diff --git a/mysql-test/suite/mariabackup/apply-log-only.test b/mysql-test/suite/mariabackup/apply-log-only.test index 96a251fc03b..5a3c45f2914 100644 --- a/mysql-test/suite/mariabackup/apply-log-only.test +++ b/mysql-test/suite/mariabackup/apply-log-only.test @@ -14,7 +14,7 @@ exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir exec $XTRABACKUP --prepare --apply-log-only --target-dir=$basedir ; let SEARCH_FILE=$MYSQLTEST_VARDIR/log/current_test; ---let SEARCH_PATTERN= Rollback of trx with id +--let SEARCH_PATTERN= Rolled back recovered transaction --source include/search_pattern_in_file.inc --echo # expect NOT FOUND diff --git a/mysql-test/suite/mariabackup/missing_ibd.result b/mysql-test/suite/mariabackup/missing_ibd.result new file mode 100644 index 00000000000..53989be7c14 --- /dev/null +++ b/mysql-test/suite/mariabackup/missing_ibd.result @@ -0,0 +1,6 @@ +create table t1(c1 int) engine=InnoDB; +INSERT INTO t1 VALUES(1); +# xtrabackup backup +select * from t1; +ERROR 42S02: Table 'test.t1' doesn't exist in engine +drop table t1; diff --git a/mysql-test/suite/mariabackup/missing_ibd.test b/mysql-test/suite/mariabackup/missing_ibd.test new file mode 100644 index 00000000000..22044e59841 --- /dev/null +++ b/mysql-test/suite/mariabackup/missing_ibd.test @@ -0,0 +1,36 @@ +--source include/have_innodb.inc + +# +# MDEV-13499: Backing up table that "doesn't exist in engine" cause crash in mariabackup when using encryption +# +create table t1(c1 int) engine=InnoDB; +INSERT INTO t1 VALUES(1); +let MYSQLD_DATADIR=`select @@datadir`; + +--disable_query_log +call mtr.add_suppression("InnoDB: Cannot open datafile for read-only: '.*test.t1\.ibd'"); +call mtr.add_suppression('InnoDB: Operating system error number'); +call mtr.add_suppression('InnoDB: The error means the system cannot find the path specified\.'); +call mtr.add_suppression('InnoDB: If you are installing InnoDB'); +call mtr.add_suppression('InnoDB: Table test/t1 in the InnoDB data dictionary has tablespace id .*, but tablespace with that id or name does not exist'); +call mtr.add_suppression('InnoDB: Ignoring tablespace for `test`\.`t1` because it could not be opened\.'); +--enable_query_log + +--source include/shutdown_mysqld.inc + +--remove_file $MYSQLD_DATADIR/test/t1.ibd + +--source include/start_mysqld.inc + +echo # xtrabackup backup; +let $targetdir=$MYSQLTEST_VARDIR/tmp/backup; +--disable_result_log +exec $XTRABACKUP --defaults-file=$MYSQLTEST_VARDIR/my.cnf --backup --target-dir=$targetdir; +--enable_result_log + +rmdir $targetdir; + +--error ER_NO_SUCH_TABLE_IN_ENGINE +select * from t1; +drop table t1; + diff --git a/mysql-test/suite/mariabackup/xb_aws_key_management.result b/mysql-test/suite/mariabackup/xb_aws_key_management.result index 6efc76a8be3..fd12344dfa0 100644 --- a/mysql-test/suite/mariabackup/xb_aws_key_management.result +++ b/mysql-test/suite/mariabackup/xb_aws_key_management.result @@ -11,6 +11,4 @@ INSERT INTO t VALUES('foobar1'); SELECT * from t; c foobar1 -Warnings: -Note 1105 AWS KMS plugin: loaded key 1, version 1, key length 128 bit DROP TABLE t; diff --git a/mysql-test/suite/mariabackup/xb_aws_key_management.test b/mysql-test/suite/mariabackup/xb_aws_key_management.test index 9f69cbec8b8..c8a12f6ed08 100644 --- a/mysql-test/suite/mariabackup/xb_aws_key_management.test +++ b/mysql-test/suite/mariabackup/xb_aws_key_management.test @@ -1,4 +1,3 @@ ---source include/innodb_page_size.inc --source include/have_debug.inc if (`SELECT COUNT(*)=0 FROM INFORMATION_SCHEMA.PLUGINS WHERE PLUGIN_NAME = 'aws_key_management' AND PLUGIN_STATUS='ACTIVE'`) diff --git a/mysql-test/suite/sys_vars/r/innodb_print_lock_wait_timeout_info_basic.result b/mysql-test/suite/sys_vars/r/innodb_print_lock_wait_timeout_info_basic.result new file mode 100644 index 00000000000..cc035e4f8bc --- /dev/null +++ b/mysql-test/suite/sys_vars/r/innodb_print_lock_wait_timeout_info_basic.result @@ -0,0 +1,104 @@ +SET @start_global_value = @@global.innodb_print_lock_wait_timeout_info; +SELECT @start_global_value; +@start_global_value +0 +Valid values are 'ON' and 'OFF' +SELECT @@global.innodb_print_lock_wait_timeout_info in (0, 1); +@@global.innodb_print_lock_wait_timeout_info in (0, 1) +1 +SELECT @@global.innodb_print_lock_wait_timeout_info; +@@global.innodb_print_lock_wait_timeout_info +0 +SELECT @@session.innodb_print_lock_wait_timeout_info; +ERROR HY000: Variable 'innodb_print_lock_wait_timeout_info' is a GLOBAL variable +SHOW global variables LIKE 'innodb_print_lock_wait_timeout_info'; +Variable_name Value +innodb_print_lock_wait_timeout_info OFF +SHOW session variables LIKE 'innodb_print_lock_wait_timeout_info'; +Variable_name Value +innodb_print_lock_wait_timeout_info OFF +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_PRINT_LOCK_WAIT_TIMEOUT_INFO OFF +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_PRINT_LOCK_WAIT_TIMEOUT_INFO OFF +SET global innodb_print_lock_wait_timeout_info='OFF'; +SELECT @@global.innodb_print_lock_wait_timeout_info; +@@global.innodb_print_lock_wait_timeout_info +0 +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_PRINT_LOCK_WAIT_TIMEOUT_INFO OFF +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_PRINT_LOCK_WAIT_TIMEOUT_INFO OFF +SET @@global.innodb_print_lock_wait_timeout_info=1; +SELECT @@global.innodb_print_lock_wait_timeout_info; +@@global.innodb_print_lock_wait_timeout_info +1 +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_PRINT_LOCK_WAIT_TIMEOUT_INFO ON +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_PRINT_LOCK_WAIT_TIMEOUT_INFO ON +SET global innodb_print_lock_wait_timeout_info=0; +SELECT @@global.innodb_print_lock_wait_timeout_info; +@@global.innodb_print_lock_wait_timeout_info +0 +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_PRINT_LOCK_WAIT_TIMEOUT_INFO OFF +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_PRINT_LOCK_WAIT_TIMEOUT_INFO OFF +SET @@global.innodb_print_lock_wait_timeout_info='ON'; +SELECT @@global.innodb_print_lock_wait_timeout_info; +@@global.innodb_print_lock_wait_timeout_info +1 +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_PRINT_LOCK_WAIT_TIMEOUT_INFO ON +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_PRINT_LOCK_WAIT_TIMEOUT_INFO ON +SET session innodb_print_lock_wait_timeout_info='OFF'; +ERROR HY000: Variable 'innodb_print_lock_wait_timeout_info' is a GLOBAL variable and should be set with SET GLOBAL +SET @@session.innodb_print_lock_wait_timeout_info='ON'; +ERROR HY000: Variable 'innodb_print_lock_wait_timeout_info' is a GLOBAL variable and should be set with SET GLOBAL +SET global innodb_print_lock_wait_timeout_info=1.1; +ERROR 42000: Incorrect argument type to variable 'innodb_print_lock_wait_timeout_info' +SET global innodb_print_lock_wait_timeout_info=1e1; +ERROR 42000: Incorrect argument type to variable 'innodb_print_lock_wait_timeout_info' +SET global innodb_print_lock_wait_timeout_info=2; +ERROR 42000: Variable 'innodb_print_lock_wait_timeout_info' can't be set to the value of '2' +SET global innodb_print_lock_wait_timeout_info=-3; +ERROR 42000: Variable 'innodb_print_lock_wait_timeout_info' can't be set to the value of '-3' +SELECT @@global.innodb_print_lock_wait_timeout_info; +@@global.innodb_print_lock_wait_timeout_info +1 +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_PRINT_LOCK_WAIT_TIMEOUT_INFO ON +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +VARIABLE_NAME VARIABLE_VALUE +INNODB_PRINT_LOCK_WAIT_TIMEOUT_INFO ON +SET global innodb_print_lock_wait_timeout_info='AUTO'; +ERROR 42000: Variable 'innodb_print_lock_wait_timeout_info' can't be set to the value of 'AUTO' +SET @@global.innodb_print_lock_wait_timeout_info = @start_global_value; +SELECT @@global.innodb_print_lock_wait_timeout_info; +@@global.innodb_print_lock_wait_timeout_info +0 diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff-disabled b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff-disabled index 5c7e310ce08..a57fc12948c 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff-disabled +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,32bit,xtradb.rdiff-disabled @@ -829,10 +829,24 @@ VARIABLE_COMMENT Page size to use for all InnoDB tablespaces. NUMERIC_MIN_VALUE 4096 NUMERIC_MAX_VALUE 65536 -@@ -1727,13 +2035,69 @@ +@@ -1727,13 +2035,83 @@ ENUM_VALUE_LIST OFF,ON READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL ++VARIABLE_NAME INNODB_PRINT_LOCK_WAIT_TIMEOUT_INFO ++SESSION_VALUE NULL ++GLOBAL_VALUE OFF ++GLOBAL_VALUE_ORIGIN COMPILE-TIME ++DEFAULT_VALUE OFF ++VARIABLE_SCOPE GLOBAL ++VARIABLE_TYPE BOOLEAN ++VARIABLE_COMMENT Print lock wait timeout info to MySQL error log (off by default) ++NUMERIC_MIN_VALUE NULL ++NUMERIC_MAX_VALUE NULL ++NUMERIC_BLOCK_SIZE NULL ++ENUM_VALUE_LIST OFF,ON ++READ_ONLY NO ++COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME INNODB_PRIORITY_CLEANER +SESSION_VALUE NULL +GLOBAL_VALUE OFF @@ -1222,7 +1236,7 @@ VARIABLE_NAME INNODB_VERSION SESSION_VALUE NULL -GLOBAL_VALUE 5.6.37 -+GLOBAL_VALUE 5.6.36-82.2 ++GLOBAL_VALUE 5.6.36-83.0 GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE NULL VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff-disabled b/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff-disabled index 6aa4e32e95e..0a2757c5138 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff-disabled +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb,xtradb.rdiff-disabled @@ -415,10 +415,24 @@ VARIABLE_NAME INNODB_MAX_DIRTY_PAGES_PCT SESSION_VALUE NULL GLOBAL_VALUE 75.000000 -@@ -1727,6 +2035,62 @@ +@@ -1727,6 +2035,76 @@ ENUM_VALUE_LIST OFF,ON READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL ++VARIABLE_NAME INNODB_PRINT_LOCK_WAIT_TIMEOUT_INFO ++SESSION_VALUE NULL ++GLOBAL_VALUE OFF ++GLOBAL_VALUE_ORIGIN COMPILE-TIME ++DEFAULT_VALUE OFF ++VARIABLE_SCOPE GLOBAL ++VARIABLE_TYPE BOOLEAN ++VARIABLE_COMMENT Print lock wait timeout info to MySQL error log (off by default) ++NUMERIC_MIN_VALUE NULL ++NUMERIC_MAX_VALUE NULL ++NUMERIC_BLOCK_SIZE NULL ++ENUM_VALUE_LIST OFF,ON ++READ_ONLY NO ++COMMAND_LINE_ARGUMENT OPTIONAL +VARIABLE_NAME INNODB_PRIORITY_CLEANER +SESSION_VALUE NULL +GLOBAL_VALUE OFF @@ -478,7 +492,7 @@ VARIABLE_NAME INNODB_PURGE_BATCH_SIZE SESSION_VALUE NULL GLOBAL_VALUE 300 -@@ -1895,6 +2259,48 @@ +@@ -1895,6 +2273,48 @@ ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL @@ -527,7 +541,7 @@ VARIABLE_NAME INNODB_SCRUB_LOG SESSION_VALUE NULL GLOBAL_VALUE OFF -@@ -1923,6 +2329,34 @@ +@@ -1923,6 +2343,34 @@ ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL @@ -562,7 +576,7 @@ VARIABLE_NAME INNODB_SIMULATE_COMP_FAILURES SESSION_VALUE NULL GLOBAL_VALUE 0 -@@ -2000,7 +2434,7 @@ +@@ -2000,7 +2448,7 @@ DEFAULT_VALUE nulls_equal VARIABLE_SCOPE GLOBAL VARIABLE_TYPE ENUM @@ -571,7 +585,7 @@ NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -@@ -2245,6 +2679,34 @@ +@@ -2245,6 +2693,34 @@ ENUM_VALUE_LIST NULL READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL @@ -606,7 +620,7 @@ VARIABLE_NAME INNODB_TRX_PURGE_VIEW_UPDATE_ONLY_DEBUG SESSION_VALUE NULL GLOBAL_VALUE OFF -@@ -2322,7 +2784,7 @@ +@@ -2322,7 +2798,7 @@ DEFAULT_VALUE OFF VARIABLE_SCOPE GLOBAL VARIABLE_TYPE BOOLEAN @@ -615,7 +629,7 @@ NUMERIC_MIN_VALUE NULL NUMERIC_MAX_VALUE NULL NUMERIC_BLOCK_SIZE NULL -@@ -2343,6 +2805,20 @@ +@@ -2343,6 +2819,20 @@ ENUM_VALUE_LIST OFF,ON READ_ONLY YES COMMAND_LINE_ARGUMENT NONE @@ -636,7 +650,7 @@ VARIABLE_NAME INNODB_USE_MTFLUSH SESSION_VALUE NULL GLOBAL_VALUE OFF -@@ -2357,6 +2833,20 @@ +@@ -2357,6 +2847,20 @@ ENUM_VALUE_LIST OFF,ON READ_ONLY YES COMMAND_LINE_ARGUMENT NONE @@ -657,12 +671,12 @@ VARIABLE_NAME INNODB_USE_SYS_MALLOC SESSION_VALUE NULL GLOBAL_VALUE ON -@@ -2387,12 +2877,12 @@ +@@ -2387,12 +2891,12 @@ COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME INNODB_VERSION SESSION_VALUE NULL -GLOBAL_VALUE 5.6.37 -+GLOBAL_VALUE 5.6.36-82.2 ++GLOBAL_VALUE 5.6.36-83.0 GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE NULL VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/r/sysvars_innodb.result b/mysql-test/suite/sys_vars/r/sysvars_innodb.result index c79b5e4de34..7f606f6f572 100644 --- a/mysql-test/suite/sys_vars/r/sysvars_innodb.result +++ b/mysql-test/suite/sys_vars/r/sysvars_innodb.result @@ -3046,7 +3046,7 @@ READ_ONLY NO COMMAND_LINE_ARGUMENT OPTIONAL VARIABLE_NAME INNODB_VERSION SESSION_VALUE NULL -GLOBAL_VALUE 5.7.20 +GLOBAL_VALUE 5.7.21 GLOBAL_VALUE_ORIGIN COMPILE-TIME DEFAULT_VALUE NULL VARIABLE_SCOPE GLOBAL diff --git a/mysql-test/suite/sys_vars/t/innodb_print_lock_wait_timeout_info_basic.test b/mysql-test/suite/sys_vars/t/innodb_print_lock_wait_timeout_info_basic.test new file mode 100644 index 00000000000..23d8ba667ce --- /dev/null +++ b/mysql-test/suite/sys_vars/t/innodb_print_lock_wait_timeout_info_basic.test @@ -0,0 +1,89 @@ +--source include/have_xtradb.inc + +SET @start_global_value = @@global.innodb_print_lock_wait_timeout_info; +SELECT @start_global_value; + +# +# exists as global only +# +--echo Valid values are 'ON' and 'OFF' +SELECT @@global.innodb_print_lock_wait_timeout_info in (0, 1); +SELECT @@global.innodb_print_lock_wait_timeout_info; +--error ER_INCORRECT_GLOBAL_LOCAL_VAR +SELECT @@session.innodb_print_lock_wait_timeout_info; +SHOW global variables LIKE 'innodb_print_lock_wait_timeout_info'; +SHOW session variables LIKE 'innodb_print_lock_wait_timeout_info'; +--disable_warnings +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +--enable_warnings + +# +# SHOW that it's writable +# +SET global innodb_print_lock_wait_timeout_info='OFF'; +SELECT @@global.innodb_print_lock_wait_timeout_info; +--disable_warnings +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +--enable_warnings +SET @@global.innodb_print_lock_wait_timeout_info=1; +SELECT @@global.innodb_print_lock_wait_timeout_info; +--disable_warnings +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +--enable_warnings +SET global innodb_print_lock_wait_timeout_info=0; +SELECT @@global.innodb_print_lock_wait_timeout_info; +--disable_warnings +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +--enable_warnings +SET @@global.innodb_print_lock_wait_timeout_info='ON'; +SELECT @@global.innodb_print_lock_wait_timeout_info; +--disable_warnings +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +--enable_warnings +--error ER_GLOBAL_VARIABLE +SET session innodb_print_lock_wait_timeout_info='OFF'; +--error ER_GLOBAL_VARIABLE +SET @@session.innodb_print_lock_wait_timeout_info='ON'; + +# +# incorrect types +# +--error ER_WRONG_TYPE_FOR_VAR +SET global innodb_print_lock_wait_timeout_info=1.1; +--error ER_WRONG_TYPE_FOR_VAR +SET global innodb_print_lock_wait_timeout_info=1e1; +--error ER_WRONG_VALUE_FOR_VAR +SET global innodb_print_lock_wait_timeout_info=2; +--error ER_WRONG_VALUE_FOR_VAR +SET global innodb_print_lock_wait_timeout_info=-3; +SELECT @@global.innodb_print_lock_wait_timeout_info; +--disable_warnings +SELECT * FROM information_schema.global_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +SELECT * FROM information_schema.session_variables +WHERE variable_name='innodb_print_lock_wait_timeout_info'; +--enable_warnings +--error ER_WRONG_VALUE_FOR_VAR +SET global innodb_print_lock_wait_timeout_info='AUTO'; + +# +# Cleanup +# + +SET @@global.innodb_print_lock_wait_timeout_info = @start_global_value; +SELECT @@global.innodb_print_lock_wait_timeout_info; diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index bd89f220060..4554be61928 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -1784,6 +1784,149 @@ create table t1(ID decimal(2,1) unsigned NOT NULL, PRIMARY KEY (ID))engine=memor select 2.1 ID; drop table t1; +# +# many keys with long names and comments +# +--error ER_CANT_CREATE_TABLE +create table t1 ( + f01 int, f02 int, f03 int, f04 int, f05 int, f06 int, f07 int, f08 int, f09 int, f10 int, f11 int, f12 int, f13 int, f14 int, f15 int, f16 int, f17 int, f18 int, f19 int, f20 int, f21 int, f22 int, f23 int, f24 int, f25 int, f26 int, f27 int, f28 int, f29 int, f30 int, f31 int, f32 int, f33 int, f34 int, f35 int, f36 int, f37 int, f38 int, f39 int, f40 int, f41 int, f42 int, f43 int, f44 int, f45 int, f46 int, f47 int, f48 int, f49 int, f50 int, f51 int, f52 int, f53 int, f54 int, f55 int, f56 int, f57 int, f58 int, f59 int, f60 int, f61 int, f62 int, f63 int, f64 int, + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0001 (f01) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0002 (f02) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0003 (f03) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0004 (f04) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0005 (f05) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0006 (f06) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0007 (f07) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0008 (f08) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0009 (f09) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0010 (f10) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0011 (f11) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0012 (f12) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0013 (f13) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0014 (f14) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0015 (f15) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0016 (f16) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0017 (f17) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0018 (f18) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0019 (f19) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0020 (f20) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0021 (f21) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0022 (f22) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0023 (f23) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0024 (f24) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0025 (f25) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0026 (f26) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0027 (f27) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0028 (f28) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0029 (f29) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0030 (f30) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0031 (f31) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0032 (f32) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0033 (f33) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0034 (f34) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0035 (f35) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0036 (f36) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0037 (f37) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0038 (f38) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0039 (f39) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0040 (f40) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0041 (f41) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0042 (f42) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0043 (f43) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0044 (f44) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0045 (f45) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0046 (f46) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0047 (f47) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0048 (f48) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0049 (f49) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0050 (f50) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0051 (f51) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0052 (f52) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0053 (f53) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0054 (f54) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0055 (f55) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0056 (f56) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0057 (f57) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0058 (f58) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0059 (f59) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0060 (f60) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0061 (f61) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0062 (f62) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0063 (f63) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0064 (f64) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + fend int); + +create table t1 ( + f01 int, f02 int, f03 int, f04 int, f05 int, f06 int, f07 int, f08 int, f09 int, f10 int, f11 int, f12 int, f13 int, f14 int, f15 int, f16 int, f17 int, f18 int, f19 int, f20 int, f21 int, f22 int, f23 int, f24 int, f25 int, f26 int, f27 int, f28 int, f29 int, f30 int, f31 int, f32 int, f33 int, f34 int, f35 int, f36 int, f37 int, f38 int, f39 int, f40 int, f41 int, f42 int, f43 int, f44 int, f45 int, f46 int, f47 int, f48 int, f49 int, f50 int, f51 int, f52 int, f53 int, f54 int, f55 int, f56 int, f57 int, f58 int, f59 int, f60 int, f61 int, f62 int, f63 int, f64 int, + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0001 (f01) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0002 (f02) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0003 (f03) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0004 (f04) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0005 (f05) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0006 (f06) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0007 (f07) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0008 (f08) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0009 (f09) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0010 (f10) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0011 (f11) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0012 (f12) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0013 (f13) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0014 (f14) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0015 (f15) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0016 (f16) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0017 (f17) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0018 (f18) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0019 (f19) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0020 (f20) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0021 (f21) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0022 (f22) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0023 (f23) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0024 (f24) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0025 (f25) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0026 (f26) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0027 (f27) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0028 (f28) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0029 (f29) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0030 (f30) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0031 (f31) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0032 (f32) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0033 (f33) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0034 (f34) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0035 (f35) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0036 (f36) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0037 (f37) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0038 (f38) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0039 (f39) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0040 (f40) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0041 (f41) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0042 (f42) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0043 (f43) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0044 (f44) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0045 (f45) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0046 (f46) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0047 (f47) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0048 (f48) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0049 (f49) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0050 (f50) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0051 (f51) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0052 (f52) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0053 (f53) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0054 (f54) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0055 (f55) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0056 (f56) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0057 (f57) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0058 (f58) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0059 (f59) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0060 (f60) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0061 (f61) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0062 (f62) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0063 (f63) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy', + fend int); +--error ER_CANT_CREATE_TABLE +alter table t1 add + key xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx0064 (f64) comment 'yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy'; +drop table t1; + --echo End of 5.5 tests # diff --git a/mysql-test/t/cte_nonrecursive.test b/mysql-test/t/cte_nonrecursive.test index a092a161277..05de03fc7af 100644 --- a/mysql-test/t/cte_nonrecursive.test +++ b/mysql-test/t/cte_nonrecursive.test @@ -929,3 +929,38 @@ select * from v; drop view v; drop table region, nation; + +--echo # +--echo # MDEV-15120: cte name used with database name +--echo # + +--error ER_NO_SUCH_TABLE +WITH cte AS (SELECT 1 AS a) SELECT test.cte.a FROM test.cte; + +CREATE DATABASE db1; +USE db1; + +--error ER_NO_SUCH_TABLE +WITH cte AS (SELECT 1 AS a) SELECT db1.cte.a FROM db1.cte; + +DROP DATABASE db1; +USE test; + +--echo # +--echo # MDEV-15119: CTE c2 specified after CTE c1 and is used in +--echo # CTE c3 that is embedded into the spec of c1 +--echo # + +CREATE TABLE t1 (i int); +INSERT INTO t1 VALUES (1),(2),(3); + +--error ER_NO_SUCH_TABLE +WITH c1 AS (WITH c3 AS (SELECT * FROM c2) SELECT * FROM c3), + c2 AS (SELECT * FROM t1) +SELECT * FROM c1; + +WITH RECURSIVE c1 AS (WITH c3 AS (SELECT * FROM c2) SELECT * FROM c3), + c2 AS (SELECT * FROM t1) +SELECT * FROM c1; + +DROP TABLE t1; diff --git a/mysql-test/t/cte_recursive.test b/mysql-test/t/cte_recursive.test index d2e33b165f7..1be645b92c0 100644 --- a/mysql-test/t/cte_recursive.test +++ b/mysql-test/t/cte_recursive.test @@ -2087,6 +2087,19 @@ set standard_compliant_cte=default; drop table flights; --echo # +--echo # MDEV-15162: Setting user variable in recursive CTE +--echo # + +SET @c=1; + +WITH RECURSIVE cte AS + (SELECT 5 + UNION + SELECT @c:=@c+1 FROM cte WHERE @c<3) +SELECT * FROM cte; + + +--echo # --echo # MDEV-14217 [db crash] Recursive CTE when SELECT includes new field --echo # diff --git a/mysql-test/t/derived.test b/mysql-test/t/derived.test index d30a6d7fd9e..466d79af409 100644 --- a/mysql-test/t/derived.test +++ b/mysql-test/t/derived.test @@ -897,6 +897,44 @@ select distinct t1.id, tt.id, tt.data drop table t1; +--echo # +--echo # MDEV-14241: Server crash in key_copy / get_matching_chain_by_join_key +--echo # or valgrind warnings +--echo # + +CREATE TABLE t1 (a VARCHAR(10)) ENGINE=MyISAM; +CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES ('foo'),('bar'); + +CREATE TABLE t2 (b integer auto_increment primary key) ENGINE=MyISAM; +INSERT INTO t2 VALUES (NULL),(NULL); + +CREATE TABLE t3 (c VARCHAR(1024) CHARACTER SET utf8, d INT) ENGINE=MyISAM; +CREATE OR REPLACE ALGORITHM=TEMPTABLE VIEW v3 AS SELECT * FROM t3; +INSERT INTO t3 VALUES ('abc',NULL),('def',4); + +SET join_cache_level= 8; +explain +SELECT * FROM v1, t2, v3 WHERE a = c AND b = d; +SELECT * FROM v1, t2, v3 WHERE a = c AND b = d; + +DROP VIEW v1, v3; +DROP TABLE t1, t2, t3; + +--echo # +--echo # MDEV-14786: Server crashes in Item_cond::transform on 2nd +--echo # execution of SP querying from a view +--echo # +create table t1 (i int, row_start timestamp(6) not null default now(), + row_end timestamp(6) not null default '2030-01-01 0:0:0'); +create view v1 as select i from t1 where i < 5 and (row_end = +TIMESTAMP'2030-01-01 0:0:0' or row_end is null); +create procedure pr(x int) select i from v1; +call pr(1); +call pr(2); +drop procedure pr; +drop view v1; +drop table t1; --echo # end of 5.5 diff --git a/mysql-test/t/dyncol.test b/mysql-test/t/dyncol.test index c0d22e9d1c4..f695d97f9f6 100644 --- a/mysql-test/t/dyncol.test +++ b/mysql-test/t/dyncol.test @@ -920,6 +920,14 @@ SELECT COLUMN_JSON(COLUMN_CREATE('a',0 AS DECIMAL,'b',1 AS DECIMAL)); SELECT COLUMN_JSON(COLUMN_CREATE('a',1 AS DECIMAL,'b',1 AS DECIMAL)); + +--echo # +--echo # MDEV-7533: COLUMN_JSON() doesn't escape control characters +--echo # in string values +--echo # +SELECT COLUMN_JSON(COLUMN_CREATE('test','"\\\t\n\Z')) AS json; +SELECT COLUMN_JSON(COLUMN_CREATE('test','First line\nSecond line')) AS json; + --echo # --echo # end of 10.0 tests --echo # diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 12d36ce645b..2e53ce7f112 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -683,6 +683,21 @@ SELECT * FROM t1 WHERE MATCH (txt1,txt2) AGAINST ('ööö1' IN BOOLEAN MODE); SELECT * FROM t1 WHERE MATCH (txt1,txt2) AGAINST ('ùùù2' IN BOOLEAN MODE); DROP TABLE t1; + +--echo # +--echo # MDEV-14743: Server crashes in Item_func_match::init_search +--echo # + +CREATE TABLE t1 (f VARCHAR(8)); +INSERT INTO t1 VALUES ('foo'),('bar'); + +SELECT 'foo' IN ( SELECT f FROM t1 GROUP BY MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE ) ); +SELECT 'foo' IN ( SELECT f FROM t1 GROUP BY MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE )) as f1, MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE ) as f2 from t1 ; +explain extended +SELECT 'foo' IN ( SELECT f FROM t1 GROUP BY MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE )) as f1, MATCH(f) AGAINST ( 'qux' IN BOOLEAN MODE ) as f2 from t1 ; + +drop table t1; + --echo # --echo # End of 5.5 tests --echo # diff --git a/mysql-test/t/func_concat.test b/mysql-test/t/func_concat.test index be573f494a2..69dd2c4063e 100644 --- a/mysql-test/t/func_concat.test +++ b/mysql-test/t/func_concat.test @@ -236,3 +236,9 @@ SELECT CONCAT(t2,'-',t2) c2 FROM (SELECT TRIM(t) t2 FROM t1) sub; DROP TABLE t1; SET optimizer_switch=@save_optimizer_switch; + +--echo # +--echo # MDEV-13790 UNHEX() of a somewhat complicated CONCAT() returns NULL +--echo # + +SELECT UNHEX(CONCAT('414C2', HEX(8 + ROUND(RAND()*7)), SUBSTR(SHA(UUID()),6,33),HEX(2+ROUND(RAND()*8)))) IS NULL AS c1; diff --git a/mysql-test/t/func_isnull.test b/mysql-test/t/func_isnull.test index 326574e0515..4c59fa3cbe8 100644 --- a/mysql-test/t/func_isnull.test +++ b/mysql-test/t/func_isnull.test @@ -38,5 +38,51 @@ INSERT INTO t1( id ) VALUES ( NULL ); SELECT t1.id FROM t1 WHERE (id is not null and id is null ); DROP TABLE t1; -# End of 5.1 tests +--echo # End of 5.1 tests +--echo # +--echo # MDEV-14911: IS NULL for field from mergeable view +--echo # + +CREATE TABLE t1 (d1 datetime NOT NULL); +INSERT INTO t1 VALUES + ('0000-00-00 00:00:00'), ('0000-00-00 00:00:00'), ('1979-09-03 20:49:36'); + +SELECT * FROM t1; +SELECT * FROM t1 WHERE d1 IS NULL; +EXPLAIN EXTENDED SELECT * FROM t1 WHERE d1 IS NULL; +SELECT count(*) FROM t1 WHERE d1 IS NULL; + +CREATE VIEW v1 AS (SELECT * FROM t1); +SELECT * FROM v1; +SELECT * FROM v1 WHERE d1 IS NULL; +EXPLAIN EXTENDED SELECT * FROM v1 WHERE d1 IS NULL; +SELECT count(*) FROM v1 WHERE d1 IS NULL; + +SET @save_optimizer_switch=@@optimizer_switch; + +SET SESSION optimizer_switch='derived_merge=off'; +SELECT count(*) FROM ( SELECT * FROM t1 ) AS a1 WHERE d1 IS NULL; +SET SESSION optimizer_switch='derived_merge=on'; +SELECT count(*) FROM ( SELECT * FROM t1 ) AS a1 WHERE d1 IS NULL; + +SET optimizer_switch=@save_optimizer_switch; + +CREATE TABLE t2 (d1 datetime NOT NULL); +INSERT INTO t2 VALUES + ('1980-09-03 20:49:36'), ('0000-00-00 00:00:00'), ('1979-09-03 20:49:36'); + +SELECT * FROM t2 LEFT JOIN t1 ON t2.d1=t1.d1 WHERE t1.d1 IS NULL; +EXPLAIN EXTENDED +SELECT * FROM t2 LEFT JOIN t1 ON t2.d1=t1.d1 WHERE t1.d1 IS NULL; + +SELECT * FROM t2 LEFT JOIN v1 ON t2.d1=v1.d1 WHERE v1.d1 IS NULL; +EXPLAIN EXTENDED +SELECT * FROM t2 LEFT JOIN v1 ON t2.d1=v1.d1 WHERE v1.d1 IS NULL; + +DROP VIEW v1; +DROP TABLE t1,t2; + +--echo # +--echo # End of 5.5 tests +--echo # diff --git a/mysql-test/t/join_cache.test b/mysql-test/t/join_cache.test index 611f5ab8942..b775725903c 100644 --- a/mysql-test/t/join_cache.test +++ b/mysql-test/t/join_cache.test @@ -3825,6 +3825,51 @@ set join_cache_level = default; DROP TABLE t1,t2; --echo # +--echo # MDEV-14960: BNLH used for materialized semi-join +--echo # + +CREATE TABLE t1 (i1 int); +CREATE TABLE t2 (e1 int); +CREATE TABLE t4 (e1 int); +CREATE TABLE t5 (e1 int); + +INSERT INTO t1 VALUES + (1),(2),(3),(4),(5),(6),(7),(8); +INSERT INTO t1 SELECT i1+8 FROM t1; +INSERT INTO t1 SELECT i1+16 FROM t1; +INSERT INTO t1 SELECT i1+32 FROM t1; +INSERT INTO t1 SELECT i1+64 FROM t1; +INSERT INTO t2 SELECT * FROM t1; +INSERT INTO t4 SELECT * FROM t1; +INSERT INTO t5 SELECT * FROM t1; + +set @save_optimizer_switch= @@optimizer_switch; +SET join_cache_level = 6; +SET join_buffer_size=4096; +SET join_buffer_space_limit=4096; +SET optimizer_switch = 'join_cache_hashed=on,optimize_join_buffer_size=on'; + +let $q= +SELECT * FROM t1 +WHERE + i1 < 10 AND + i1 IN + (SELECT i1 FROM + (SELECT (t4.e1) i1 FROM t4 + LEFT JOIN t5 ON t4.e1 = t5.e1 + LEFT JOIN (SELECT e1 FROM t2 ) AS d ON t4.e1 = d.e1) a); + +eval EXPLAIN $q; +eval $q; + +SET join_cache_level = default; +SET join_buffer_size = default; +SET join_buffer_space_limit= default; +set optimizer_switch=@save_optimizer_switch; + +DROP TABLE t1,t4,t5,t2; + +--echo # --echo # MDEV-5123 Remove duplicated conditions pushed both to join_tab->select_cond and join_tab->cache_select->cond for blocked joins. --echo # diff --git a/mysql-test/t/mdev_14586.test b/mysql-test/t/mdev_14586.test new file mode 100644 index 00000000000..8b3d3780151 --- /dev/null +++ b/mysql-test/t/mdev_14586.test @@ -0,0 +1,27 @@ +create table t1(a bit(1), b int auto_increment ,id int, index(a,b)); +insert into t1 values(1,null,1); +insert into t1 values(1,null,2); +insert into t1 values(0,null,3); +insert into t1 values(0,null,4); +select a+0, b as auto_increment , id from t1 order by id; +drop table t1; +create table t1(a int auto_increment, b bit(5) ,id int, index (b,a)); +insert into t1 values(null,b'1',1); +insert into t1 values(null,b'1',2); +insert into t1 values(null,b'11',3); +insert into t1 values(null,b'11',4); +select a as auto_increment, b+0, id from t1 order by id; +drop table t1; +create table t1(a bit(1), b int auto_increment , c bit(1) , d bit(1), id int,index(a,c,b,d)); +insert into t1 values(1,null,1,1,1); +insert into t1 values(1,null,1,1,2); +insert into t1 values(0,null,1,1,3); +insert into t1 values(1,null,0,1,4); +select a+0, b as auto_increment, c+0, d+0, id from t1 order by id; +drop table t1; +CREATE TABLE t1 (b BIT(1), pk INTEGER AUTO_INCREMENT PRIMARY KEY); +ALTER TABLE t1 ADD INDEX(b,pk); +INSERT INTO t1 VALUES (1,b'1'); +ALTER TABLE t1 DROP PRIMARY KEY; +select b+0, pk as auto_increment from t1; +DROP TABLE t1; diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index 99309e6a7f0..f5771305dc4 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -1559,7 +1559,7 @@ CREATE TABLE m1 ( ) ENGINE=MRG_MyISAM DEFAULT CHARSET=latin1 INSERT_METHOD=LAST UNION=(t1); insert into m1 (col1) values (1); ---error ER_DUP_ENTRY +--error ER_DUP_KEY insert into m1 (col1) values (1); drop table m1, t1; @@ -1593,7 +1593,7 @@ CREATE TABLE t1 (c1 INT, c2 INT, UNIQUE (c1), UNIQUE (c2)); CREATE TABLE m1 (c1 INT, c2 INT, UNIQUE (c1)) ENGINE=MRG_MyISAM INSERT_METHOD=LAST UNION=(t1); INSERT INTO m1 VALUES (1,2); --echo # insert the duplicate value into the merge table ---error ER_DUP_ENTRY +--error ER_DUP_KEY INSERT INTO m1 VALUES (3,2); DROP TABLE m1,t1; diff --git a/mysql-test/t/myisam_optimize.test b/mysql-test/t/myisam_optimize.test index 5f0b8fc7666..5e133aea853 100644 --- a/mysql-test/t/myisam_optimize.test +++ b/mysql-test/t/myisam_optimize.test @@ -46,3 +46,20 @@ connection default; drop table t1; set debug_sync='reset'; +--echo # End of 5.5 tests + +# +# MDEV-11539 test_if_reopen: Assertion `strcmp(share->unique_file_name,filename) || share->last_version' failed upon select from I_S +# +CREATE TABLE t1 (i INT) ENGINE=MyISAM; +INSERT t1 VALUES (1); +LOCK TABLE t1 WRITE; +OPTIMIZE TABLE t1; +--disable_result_log +SELECT * FROM INFORMATION_SCHEMA.TABLES; +--enable_result_log +SELECT * FROM t1; +UNLOCK TABLES; +DROP TABLE t1; + +--echo # End of 10.0 tests diff --git a/mysql-test/t/mysqldump-nl.test b/mysql-test/t/mysqldump-nl.test index 311996e77c3..4513fb2c637 100644 --- a/mysql-test/t/mysqldump-nl.test +++ b/mysql-test/t/mysqldump-nl.test @@ -36,3 +36,23 @@ show tables from `mysqltest1 drop database `mysqltest1 1tsetlqsym`; + +create database `test```; +create database `test\`` +\! ls +#`; + +show databases like 'test%'; + +exec $MYSQL_DUMP --compact --comment --add-drop-database --databases 'test`' 'test\` +\! ls +#'; + +exec $MYSQL_DUMP --compact --comment --add-drop-database --databases 'test`' 'test\` +\! ls +#' | $MYSQL; + +drop database `test```; +drop database `test\`` +\! ls +#`; diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test index 914911648b2..b047a31c863 100644 --- a/mysql-test/t/order_by.test +++ b/mysql-test/t/order_by.test @@ -1958,6 +1958,44 @@ UNION ORDER BY NULL, @a0 := 3, @a1 := 3, @a2 := 3, @a3 := 3, @a4 := 3, @a5 := 3, @a6 := 3, @a7 := 3, @a8 := 3, @a9 := 3, @a10 := 3 ); + +--echo # +--echo # mdev-6706: semi-join with duplicate weedout + ORDER BY +--echo # + +CREATE TABLE t1 (f1 VARCHAR(3)) ENGINE=MyISAM; +INSERT INTO t1 VALUES ('foo'); + +CREATE TABLE t2 (f2 VARCHAR(3)) ENGINE=MyISAM; +INSERT INTO t2 VALUES ('bar'),('baz'); + +CREATE TABLE t3 +(i3_key INT, f3_key VARCHAR(3), f3 VARCHAR(3), KEY(f3_key,i3_key)) + ENGINE=MyISAM; +INSERT INTO t3 VALUES (0,'qux','qux'),(8,'bar','bar'); + +let $q1= +SELECT CONCAT( f1, f2 ) AS field FROM t1, t2 +WHERE f1 = ANY ( SELECT f1 + FROM t1 + LEFT JOIN ( t3 AS t3a, t3 AS t3b ) + ON ( t3b.f3_key = t3a.f3 ) + WHERE t3a.f3 < f1 OR t3b.f3 != f1 ); +let $q2= +SELECT CONCAT( f1, f2 ) AS field FROM t1, t2 +WHERE f1 = ANY ( SELECT f1 + FROM t1 + LEFT JOIN ( t3 AS t3a, t3 AS t3b ) + ON ( t3b.f3_key = t3a.f3 ) + WHERE t3a.f3 < f1 OR t3b.f3 != f1 ) +ORDER BY field; + +eval $q1; +eval $q2; +eval EXPLAIN EXTENDED $q2; + +DROP TABLE t1,t2,t3; + --echo End of 5.5 tests --echo # diff --git a/mysql-test/t/partition.test b/mysql-test/t/partition.test index 608c8812e01..dfb0966d5dd 100644 --- a/mysql-test/t/partition.test +++ b/mysql-test/t/partition.test @@ -2885,8 +2885,21 @@ alter table t1 drop partition if exists p5; DROP TABLE t1; +# +# MDEV-14696 Server crashes in in prep_alter_part_table on 2nd execution of PS. +# + +CREATE TABLE t1 (a INT) ENGINE=MyISAM PARTITION BY RANGE(a) (PARTITION p1 VALUES LESS THAN (0)); +ALTER TABLE t1 ADD PARTITION (PARTITION p2 VALUES LESS THAN (1)); +PREPARE stmt FROM 'ALTER TABLE t1 ADD PARTITION IF NOT EXISTS (PARTITION p2 VALUES LESS THAN (2))'; +EXECUTE stmt; +EXECUTE stmt; + +DEALLOCATE PREPARE stmt; +DROP TABLE t1; + --echo # ---echo # Start of 10.1 tests +--echo # End of 10.0 tests --echo # --echo # diff --git a/mysql-test/t/partition_innodb.test b/mysql-test/t/partition_innodb.test index 300121e88fd..7b5a69fe622 100644 --- a/mysql-test/t/partition_innodb.test +++ b/mysql-test/t/partition_innodb.test @@ -991,3 +991,31 @@ SELECT b FROM t1 WHERE b = 0; SELECT b FROM t1 WHERE b = 0; --disconnect con1 DROP TABLE t1; + +--echo # +--echo # Bug#26390658 RENAMING A PARTITIONED TABLE DOES NOT UPDATE +--echo # MYSQL.INNODB_TABLE_STATS +--echo # + +CREATE DATABASE test_jfg; + +CREATE TABLE test_jfg.test_jfg1 (id int(10) unsigned NOT NULL,PRIMARY +KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=latin1 STATS_PERSISTENT=1; +CREATE TABLE test_jfg.test_jfg2 (id int(10) unsigned NOT NULL,PRIMARY +KEY (id)) ENGINE=InnoDB DEFAULT CHARSET=latin1 STATS_PERSISTENT=1 +PARTITION BY RANGE ( id ) (PARTITION p1000 VALUES LESS THAN (1000) +ENGINE = InnoDB,PARTITION pmax VALUES LESS THAN MAXVALUE ENGINE = +InnoDB); + +--replace_result #p# #P# +SELECT database_name, table_name FROM mysql.innodb_table_stats WHERE +database_name = 'test_jfg'; + +RENAME TABLE test_jfg.test_jfg1 TO test_jfg.test_jfg11; +RENAME TABLE test_jfg.test_jfg2 TO test_jfg.test_jfg12; + +--replace_result #p# #P# +SELECT database_name, table_name FROM mysql.innodb_table_stats WHERE +database_name = 'test_jfg'; + +DROP DATABASE test_jfg; diff --git a/mysql-test/t/query_cache_debug.test b/mysql-test/t/query_cache_debug.test index 31f2d786efb..22ff1d45e63 100644 --- a/mysql-test/t/query_cache_debug.test +++ b/mysql-test/t/query_cache_debug.test @@ -299,3 +299,55 @@ RESET QUERY CACHE; DROP TABLE t1; SET GLOBAL query_cache_size= DEFAULT; SET GLOBAL query_cache_type= DEFAULT; + +--echo # +--echo # MDEV-14526: MariaDB keeps crashing under load when +--echo # query_cache_type is changed +--echo # + +CREATE TABLE t1 ( + `id` int(10) NOT NULL AUTO_INCREMENT, + `k` int(10) default '0', + PRIMARY KEY (`id`)) +ENGINE=MyISAM; + +INSERT IGNORE INTO t1 VALUES + (NULL,1),(NULL,8),(NULL,NULL),(NULL,NULL),(NULL,4),(NULL,9),(NULL,7), + (NULL,3),(NULL,NULL),(NULL,2),(NULL,3),(NULL,NULL),(NULL,2),(NULL,7), + (NULL,1),(NULL,2),(NULL,4),(NULL,NULL),(NULL,1),(NULL,1),(NULL,4); + +SET GLOBAL query_cache_size= 1024*1024; +SET GLOBAL query_cache_type= 1; + +--connect (con2,localhost,root,,test) +--connect (con1,localhost,root,,test) +set debug_sync="wait_in_query_cache_store_query SIGNAL parked WAIT_FOR go"; +--send + + SELECT DISTINCT id FROM t1 WHERE id BETWEEN 5603 AND 16218 ORDER BY k; + +--connection default + +set debug_sync="now WAIT_FOR parked"; +--connection con2 +--send + SET GLOBAL query_cache_type= 0; + +--connection default +set debug_sync="now SIGNAL go"; + +--connection con1 +--reap +--connection con2 +--reap + +# Cleanup +--disconnect con1 +--disconnect con2 +--connection default +set debug_sync= 'RESET'; +DROP TABLE t1; +SEt GLOBAL query_cache_size= DEFAULT; +SEt GLOBAL query_cache_type= DEFAULT; + +--echo # End of 5.5 tests diff --git a/mysql-test/t/repair.test b/mysql-test/t/repair.test index a6df0dc5979..5494e370133 100644 --- a/mysql-test/t/repair.test +++ b/mysql-test/t/repair.test @@ -115,7 +115,7 @@ SET myisam_repair_threads=@@global.myisam_repair_threads; SET myisam_sort_buffer_size=@@global.myisam_sort_buffer_size; DROP TABLE t1; ---echo End of 4.1 tests +--echo # End of 4.1 tests # # BUG#36055 - mysql_upgrade doesn't really 'upgrade' tables @@ -147,7 +147,8 @@ REPAIR TABLE t1 USE_FRM; SELECT * FROM t1; DROP TABLE t1; -# End of 5.0 tests + +--echo # End of 5.0 tests # # Bug#18775 - Temporary table from alter table visible to other threads @@ -219,3 +220,21 @@ create view v1 as select * from t1; repair view v1; drop view v1; drop table t1; + +--echo # End of 5.5 tests + +# +# MDEV-11539 test_if_reopen: Assertion `strcmp(share->unique_file_name,filename) || share->last_version' failed upon select from I_S +# +CREATE TABLE t1 (i INT) ENGINE=MyISAM; +INSERT t1 VALUES (1); +LOCK TABLE t1 WRITE; +REPAIR TABLE t1; +--disable_result_log +SELECT * FROM INFORMATION_SCHEMA.TABLES; +--enable_result_log +SELECT * FROM t1; +UNLOCK TABLES; +DROP TABLE t1; + +--echo # End of 10.0 tests diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 5ddf4153497..4e87ba0c220 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -9598,6 +9598,155 @@ DROP FUNCTION f1; DROP VIEW v1; DROP TABLE t1; +--echo # +--echo # MDEV-14857: problem with 10.2.11 server crashing when +--echo # executing stored procedure +--echo # + +SET max_sp_recursion_depth=10; + +CREATE TABLE t1 (a INT); +CREATE TABLE t2 (b INT); + +delimiter ||; + +CREATE PROCEDURE proc_0() +BEGIN + CALL empty_1(); + CALL proc_1(); +END || + +CREATE PROCEDURE proc_1() +BEGIN + CALL proc_2(); + CALL proc_3(); + CALL proc_4(); + CALL proc_5(); +END || + +CREATE PROCEDURE proc_2() + CALL proc_6(); +|| + +CREATE PROCEDURE proc_3() +BEGIN + CALL empty_2(); + CALL empty_3(); +END || + +CREATE PROCEDURE proc_4() + CALL proc_7(); +|| + +CREATE PROCEDURE proc_5() + CALL proc_select(); +|| + +CREATE PROCEDURE proc_6() +BEGIN + CALL empty_4(); + CALL empty_5(); + CALL empty_6(); + CALL empty_7(); + CALL proc_8(); +END || + +CREATE PROCEDURE proc_7() + CALL proc_9('foo'); +|| + +CREATE PROCEDURE proc_8() + CALL proc_10(); +|| + +CREATE PROCEDURE proc_9(IN opt VARCHAR(40)) + IF LEFT(opt,1) <> '_' THEN + CALL proc_11(); + END IF; +|| + +CREATE PROCEDURE proc_10() + CALL proc_12(); +|| + +CREATE PROCEDURE proc_11() +BEGIN + CALL empty_8(); + CALL empty_9(); + CALL empty_10(); + CALL proc_13(); +END || + +CREATE PROCEDURE proc_12() +BEGIN + CALL empty_11(); + CALL empty_12(); + CALL empty_13(); +END || + +CREATE PROCEDURE proc_13() +BEGIN + CALL proc_9('_bar'); + CALL empty_14(); +END || + +delimiter ;|| + +CREATE PROCEDURE empty_1() BEGIN END ; +CREATE PROCEDURE empty_2() BEGIN END ; +CREATE PROCEDURE empty_3() BEGIN END ; +CREATE PROCEDURE empty_4() BEGIN END ; +CREATE PROCEDURE empty_5() BEGIN END ; +CREATE PROCEDURE empty_6() BEGIN END ; +CREATE PROCEDURE empty_7() BEGIN END ; +CREATE PROCEDURE empty_8() BEGIN END ; +CREATE PROCEDURE empty_9() BEGIN END ; +CREATE PROCEDURE empty_10() BEGIN END ; +CREATE PROCEDURE empty_11() BEGIN END ; +CREATE PROCEDURE empty_12() BEGIN END ; +CREATE PROCEDURE empty_13() BEGIN END ; +CREATE PROCEDURE empty_14() BEGIN END ; + +CREATE PROCEDURE proc_select() + SELECT * FROM t1 WHERE NOT EXISTS ( SELECT * FROM t2) +; + +CALL proc_0(); + +# Cleanup +DROP PROCEDURE empty_1; +DROP PROCEDURE empty_2; +DROP PROCEDURE empty_3; +DROP PROCEDURE empty_4; +DROP PROCEDURE empty_5; +DROP PROCEDURE empty_6; +DROP PROCEDURE empty_7; +DROP PROCEDURE empty_8; +DROP PROCEDURE empty_9; +DROP PROCEDURE empty_10; +DROP PROCEDURE empty_11; +DROP PROCEDURE empty_12; +DROP PROCEDURE empty_13; +DROP PROCEDURE empty_14; +DROP PROCEDURE proc_0; +DROP PROCEDURE proc_1; +DROP PROCEDURE proc_2; +DROP PROCEDURE proc_3; +DROP PROCEDURE proc_4; +DROP PROCEDURE proc_5; +DROP PROCEDURE proc_6; +DROP PROCEDURE proc_7; +DROP PROCEDURE proc_8; +DROP PROCEDURE proc_9; +DROP PROCEDURE proc_10; +DROP PROCEDURE proc_11; +DROP PROCEDURE proc_12; +DROP PROCEDURE proc_13; +DROP PROCEDURE proc_select; +DROP TABLE t1, t2; + +SET max_sp_recursion_depth=default; + --echo #End of 10.1 tests --echo # diff --git a/mysql-test/t/thread_id_overflow.test b/mysql-test/t/thread_id_overflow.test new file mode 100644 index 00000000000..e93e14f4284 --- /dev/null +++ b/mysql-test/t/thread_id_overflow.test @@ -0,0 +1,35 @@ +# test 32bit overflow with connection id +--source include/have_debug.inc + + +# Connect and disconnect once, to create a "hole" in connection ids +connect con1, localhost,root; +disconnect con1; + +connect con2, localhost,root; +connection con2; + +connection default; +let $max_id = `SELECT MAX(ID) FROM INFORMATION_SCHEMA.PROCESSLIST`; + +SET @orig_debug=@@debug_dbug; +SET GLOBAL DEBUG_DBUG='+d,thread_id_overflow'; + +connect con3, localhost,root; +connection con3; +# next line gives UINT32_MAX -1; +SELECT CONNECTION_ID(); + +connection default; +SET GLOBAL DEBUG_DBUG=@orig_debug; + +connect con4, localhost,root; +connection con4; +--replace_result $max_id max_id +eval select IF(connection_id() - $max_id = 1,'Good','Bad') as result; + +disconnect con4; +disconnect con3; +disconnect con2; + +connection default; diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index a2e1fd09ade..f86cae87524 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -1434,6 +1434,42 @@ select e,f, (e , f) in (select e,b from t1 union select c,d from t2) as sub from select avg(f), (e , f) in (select e,b from t1 union select c,d from t2) as sub from t3 group by sub; drop table t1,t2,t3; +--echo # +--echo # MDEV-14715 Assertion `!table || (!table->read_set || +--echo # bitmap_is_set(table->read_set, field_index))' +--echo # failed in Field_num::val_decimal +--echo # + +CREATE TABLE t1 (a INT, b INT) ENGINE=MyISAM; +CREATE VIEW v1 AS SELECT * FROM t1; +INSERT INTO t1 VALUES (1, NULL),(3, 4); + +(SELECT a, sum(a) AS f FROM v1 group by a ORDER BY b + sum(a)) +UNION +(SELECT 2, 2); + +(SELECT a, sum(a) AS f FROM v1 group by a ORDER BY b + 1) +UNION +(SELECT 2, 2); + +SELECT a, b FROM t1 +UNION +(SELECT a, VAR_POP(a) AS f FROM v1 GROUP BY a ORDER BY b/a ); + +DROP TABLE t1; + +--error ER_VIEW_INVALID +(SELECT a, sum(a) AS f FROM v1 group by a ORDER BY b + 1) +UNION +(SELECT 2, 2); + +DROP VIEW v1; + +--error ER_NO_SUCH_TABLE +(SELECT a, sum(a) AS f FROM v1 group by a ORDER BY b + 1) +UNION +(SELECT 2, 2); + --echo End of 5.5 tests --echo # diff --git a/mysql-test/t/update_innodb.test b/mysql-test/t/update_innodb.test index 0e93e7d9593..acc8aceab00 100644 --- a/mysql-test/t/update_innodb.test +++ b/mysql-test/t/update_innodb.test @@ -39,6 +39,18 @@ drop view v1; drop table t1,t2,t3,t4; --echo # +--echo # MDEV-14862: Server crashes in Bitmap<64u>::merge / add_key_field +--echo # + +CREATE TABLE t1 (a INT) ENGINE=InnoDB; +CREATE VIEW v1 AS SELECT * FROM t1; +CREATE TABLE t2 (b INT) ENGINE=InnoDB; +DELETE FROM v1 WHERE a IN ( SELECT a FROM t2 ); +DELETE FROM v1 WHERE (a,a) IN ( SELECT a,a FROM t2 ); +drop view v1; +drop table t1,t2; + +--echo # --echo # MDEV-10232 Scalar result of subquery changes after adding an outer select stmt --echo # diff --git a/mysql-test/t/xa.test b/mysql-test/t/xa.test index b26f3f3c73f..736d0c0de29 100644 --- a/mysql-test/t/xa.test +++ b/mysql-test/t/xa.test @@ -374,6 +374,20 @@ DROP TABLE t1; --echo # +--echo # MDEV-14609 XA Transction unable to ROLLBACK TO SAVEPOINT +--echo # + +CREATE TABLE t1 (c1 INT) ENGINE=INNODB; +XA START 'xa1'; +SAVEPOINT savepoint1; +INSERT INTO t1 (c1) VALUES (1),(2),(3),(4); +ROLLBACK TO SAVEPOINT savepoint1; +XA END 'xa1'; +XA ROLLBACK 'xa1'; +DROP TABLE t1; + + +--echo # --echo # Bug#12352846 - TRANS_XA_START(THD*): --echo # ASSERTION THD->TRANSACTION.XID_STATE.XID.IS_NULL() --echo # FAILED diff --git a/mysql-test/t/xml.test b/mysql-test/t/xml.test index bbb2ca7948f..b567f03a431 100644 --- a/mysql-test/t/xml.test +++ b/mysql-test/t/xml.test @@ -748,6 +748,15 @@ SELECT *,IF(@i:=c1,ExtractValue('<a><b>b1</b><b>b2</b></a>','//b[$@i]'),0) AS xp SELECT * FROM t1 WHERE c2=IF(@i:=c1,ExtractValue('<a><b>b1</b><b>b2</b></a>','//b[$@i]'),0); DROP TABLE t1; +--echo # +--echo # MDEV-15118 ExtractValue(xml,something_complex) does not work +--echo # + +CREATE TABLE t1 (a TEXT); +INSERT INTO t1 VALUES (CONCAT('<a>aaa</a>')); +SELECT ExtractValue(a, '/a') AS a FROM t1; +SELECT ExtractValue(a, FROM_BASE64(TO_BASE64('/a'))) AS a FROM t1; +DROP TABLE t1; --echo # --echo # End of 10.0 tests diff --git a/mysys/ma_dyncol.c b/mysys/ma_dyncol.c index 3c15e373182..2e00ca72f74 100644 --- a/mysys/ma_dyncol.c +++ b/mysys/ma_dyncol.c @@ -3818,6 +3818,58 @@ end: DBUG_RETURN(rc); } +static +my_bool dynstr_append_json_quoted(DYNAMIC_STRING *str, + const char *append, size_t len) +{ + uint additional= ((str->alloc_increment && str->alloc_increment > 6) ? + str->alloc_increment : + 10); + uint lim= additional; + uint i; + if (dynstr_realloc(str, len + additional + 2)) + return TRUE; + str->str[str->length++]= '"'; + for (i= 0; i < len; i++) + { + register char c= append[i]; + if (unlikely(c <= 0x1F)) + { + if (lim < 5) + { + if (dynstr_realloc(str, additional)) + return TRUE; + lim+= additional; + } + lim-= 5; + str->str[str->length++]= '\\'; + str->str[str->length++]= 'u'; + str->str[str->length++]= '0'; + str->str[str->length++]= '0'; + str->str[str->length++]= (c < 0x10 ? '0' : '1'); + c%= 0x10; + str->str[str->length++]= (c < 0xA ? '0' + c : 'A' + (c - 0xA)); + } + else + { + if (c == '"' || c == '\\') + { + if (!lim) + { + if (dynstr_realloc(str, additional)) + return TRUE; + lim= additional; + } + lim--; + str->str[str->length++]= '\\'; + } + str->str[str->length++]= c; + } + } + str->str[str->length++]= '"'; + return FALSE; +} + enum enum_dyncol_func_result mariadb_dyncol_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val, @@ -3883,7 +3935,10 @@ mariadb_dyncol_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val, return ER_DYNCOL_RESOURCE; } if (quote) - rc= dynstr_append_quoted(str, from, len, quote); + if (quote == DYNCOL_JSON_ESC) + rc= dynstr_append_json_quoted(str, from, len); + else + rc= dynstr_append_quoted(str, from, len, quote); else rc= dynstr_append_mem(str, from, len); if (alloc) @@ -4183,7 +4238,8 @@ mariadb_dyncol_json_internal(DYNAMIC_COLUMN *str, DYNAMIC_STRING *json, } else { - if ((rc= mariadb_dyncol_val_str(json, &val, DYNCOL_UTF, '"')) < 0) + if ((rc= mariadb_dyncol_val_str(json, &val, DYNCOL_UTF, DYNCOL_JSON_ESC)) + < 0) goto err; } } diff --git a/mysys/mf_iocache.c b/mysys/mf_iocache.c index 4dd0f7500aa..09adb704622 100644 --- a/mysys/mf_iocache.c +++ b/mysys/mf_iocache.c @@ -272,7 +272,7 @@ int init_io_cache(IO_CACHE *info, File file, size_t cachesize, else { /* Clear mutex so that safe_mutex will notice that it's not initialized */ - bzero((char*) &info->append_buffer_lock, sizeof(info)); + bzero((char*) &info->append_buffer_lock, sizeof(info->append_buffer_lock)); } #endif diff --git a/mysys/my_addr_resolve.c b/mysys/my_addr_resolve.c index 83716bf11e1..10f8552f226 100644 --- a/mysys/my_addr_resolve.c +++ b/mysys/my_addr_resolve.c @@ -34,13 +34,6 @@ static const char *strip_path(const char *s) return prev; } -#if defined(HAVE_LINK_H) && defined(HAVE_DLOPEN) -#include <link.h> -static ptrdiff_t offset= 0; -#else -#define offset 0 -#endif - /* The following is very much single-threaded code and it's only supposed to be used on shutdown or for a crash report @@ -145,10 +138,52 @@ err: #include <m_string.h> #include <ctype.h> +#include <sys/wait.h> static int in[2], out[2]; -static int initialized= 0; +static pid_t pid; +static char addr2line_binary[1024]; static char output[1024]; + +int start_addr2line_fork(const char *binary_path) +{ + + if (pid > 0) + { + /* Don't leak FDs */ + close(in[1]); + close(out[0]); + /* Don't create zombie processes. */ + waitpid(pid, NULL, 0); + } + + if (pipe(in) < 0) + return 1; + if (pipe(out) < 0) + return 1; + + pid = fork(); + if (pid == -1) + return 1; + + if (!pid) /* child */ + { + dup2(in[0], 0); + dup2(out[1], 1); + close(in[0]); + close(in[1]); + close(out[0]); + close(out[1]); + execlp("addr2line", "addr2line", "-C", "-f", "-e", binary_path, NULL); + exit(1); + } + + close(in[0]); + close(out[1]); + + return 0; +} + int my_addr_resolve(void *ptr, my_addr_loc *loc) { char input[32]; @@ -156,69 +191,88 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) ssize_t total_bytes_read = 0; ssize_t extra_bytes_read = 0; + ssize_t parsed = 0; fd_set set; struct timeval timeout; int filename_start = -1; int line_number_start = -1; - ssize_t i; - FD_ZERO(&set); - FD_SET(out[0], &set); + Dl_info info; + void *offset; + if (!dladdr(ptr, &info)) + return 1; + + if (strcmp(addr2line_binary, info.dli_fname)) + { + /* We use dli_fname in case the path is longer than the length of our static + string. We don't want to allocate anything dynamicaly here as we are in + a "crashed" state. */ + if (start_addr2line_fork(info.dli_fname)) + { + addr2line_binary[0] = '\0'; + return 2; + } + /* Save result for future comparisons. */ + strnmov(addr2line_binary, info.dli_fname, sizeof(addr2line_binary)); + } + offset = info.dli_fbase; len= my_snprintf(input, sizeof(input), "%p\n", ptr - offset); if (write(in[1], input, len) <= 0) - return 1; + return 3; + + FD_ZERO(&set); + FD_SET(out[0], &set); - /* 10 ms should be plenty of time for addr2line to issue a response. */ + /* 100 ms should be plenty of time for addr2line to issue a response. */ timeout.tv_sec = 0; - timeout.tv_usec = 10000; + timeout.tv_usec = 100000; /* Read in a loop till all the output from addr2line is complete. */ - while (select(out[0] + 1, &set, NULL, NULL, &timeout) > 0) + while (parsed == total_bytes_read && + select(out[0] + 1, &set, NULL, NULL, &timeout) > 0) { extra_bytes_read= read(out[0], output + total_bytes_read, sizeof(output) - total_bytes_read); if (extra_bytes_read < 0) - return 2; + return 4; /* Timeout or max bytes read. */ if (extra_bytes_read == 0) break; total_bytes_read += extra_bytes_read; - } - - /* Failed starting addr2line. */ - if (total_bytes_read == 0) - return 3; - /* Go through the addr2line response and get the required data. - The response is structured in 2 lines. The first line contains the function - name, while the second one contains <filename>:<line number> */ - for (i = 0; i < total_bytes_read; i++) { - if (output[i] == '\n') { - filename_start = i + 1; - output[i] = '\0'; - } - if (filename_start != -1 && output[i] == ':') { - line_number_start = i + 1; - output[i] = '\0'; - } - if (line_number_start != -1) { - loc->line= atoi(output + line_number_start); - break; + /* Go through the addr2line response and get the required data. + The response is structured in 2 lines. The first line contains the function + name, while the second one contains <filename>:<line number> */ + for (; parsed < total_bytes_read; parsed++) + { + if (output[parsed] == '\n') + { + filename_start = parsed + 1; + output[parsed] = '\0'; + } + if (filename_start != -1 && output[parsed] == ':') + { + line_number_start = parsed + 1; + output[parsed] = '\0'; + break; + } } } + /* Response is malformed. */ if (filename_start == -1 || line_number_start == -1) - return 4; + return 5; loc->func= output; loc->file= output + filename_start; + loc->line= atoi(output + line_number_start); /* Addr2line was unable to extract any meaningful information. */ if (strcmp(loc->file, "??") == 0) - return 5; + return 6; loc->file= strip_path(loc->file); @@ -227,41 +281,6 @@ int my_addr_resolve(void *ptr, my_addr_loc *loc) const char *my_addr_resolve_init() { - if (!initialized) - { - pid_t pid; - -#if defined(HAVE_LINK_H) && defined(HAVE_DLOPEN) - struct link_map *lm = (struct link_map*) dlopen(0, RTLD_NOW); - if (lm) - offset= lm->l_addr; -#endif - - if (pipe(in) < 0) - return "pipe(in)"; - if (pipe(out) < 0) - return "pipe(out)"; - - pid = fork(); - if (pid == -1) - return "fork"; - - if (!pid) /* child */ - { - dup2(in[0], 0); - dup2(out[1], 1); - close(in[0]); - close(in[1]); - close(out[0]); - close(out[1]); - execlp("addr2line", "addr2line", "-C", "-f", "-e", my_progname, NULL); - exit(1); - } - - close(in[0]); - close(out[1]); - initialized= 1; - } return 0; } #endif diff --git a/mysys/my_alloc.c b/mysys/my_alloc.c index 0dbd571c7fd..7139466be17 100644 --- a/mysys/my_alloc.c +++ b/mysys/my_alloc.c @@ -26,6 +26,8 @@ #define MALLOC_FLAG(A) ((A & 1) ? MY_THREAD_SPECIFIC : 0) +#define TRASH_MEM(X) TRASH_FREE(((char*)(X) + ((X)->size-(X)->left)), (X)->left) + /* Initialize memory root @@ -76,13 +78,14 @@ void init_alloc_root(MEM_ROOT *mem_root, const char *name, size_t block_size, if (pre_alloc_size) { if ((mem_root->free= mem_root->pre_alloc= - (USED_MEM*) my_malloc(pre_alloc_size+ ALIGN_SIZE(sizeof(USED_MEM)), - MYF(my_flags)))) + (USED_MEM*) my_malloc(pre_alloc_size + ALIGN_SIZE(sizeof(USED_MEM)), + MYF(my_flags)))) { mem_root->free->size= pre_alloc_size+ALIGN_SIZE(sizeof(USED_MEM)); mem_root->total_alloc= pre_alloc_size+ALIGN_SIZE(sizeof(USED_MEM)); mem_root->free->left= pre_alloc_size; mem_root->free->next= 0; + TRASH_MEM(mem_root->free); } } #endif @@ -154,6 +157,7 @@ void reset_root_defaults(MEM_ROOT *mem_root, size_t block_size, mem->left= pre_alloc_size; mem->next= *prev; *prev= mem_root->pre_alloc= mem; + TRASH_MEM(mem); } else { @@ -257,6 +261,7 @@ void *alloc_root(MEM_ROOT *mem_root, size_t length) next->size= get_size; next->left= get_size-ALIGN_SIZE(sizeof(USED_MEM)); *prev=next; + TRASH_MEM(next); } point= (uchar*) ((char*) next+ (next->size-next->left)); @@ -329,7 +334,6 @@ void *multi_alloc_root(MEM_ROOT *root, ...) DBUG_RETURN((void*) start); } -#define TRASH_MEM(X) TRASH(((char*)(X) + ((X)->size-(X)->left)), (X)->left) #if !(defined(HAVE_valgrind) && defined(EXTRA_DEBUG)) /** Mark all data in blocks free for reusage */ diff --git a/mysys/my_default.c b/mysys/my_default.c index eed87341d8e..ddcc869fa66 100644 --- a/mysys/my_default.c +++ b/mysys/my_default.c @@ -1,4 +1,5 @@ -/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved. +/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2011, 2018, MariaDB Corporation 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 @@ -233,7 +234,7 @@ int my_search_option_files(const char *conf_file, int *argc, char ***argv, (char **) &my_defaults_group_suffix); if (! my_defaults_group_suffix) - my_defaults_group_suffix= getenv(STRINGIFY_ARG(DEFAULT_GROUP_SUFFIX_ENV)); + my_defaults_group_suffix= getenv("MYSQL_GROUP_SUFFIX"); if (forced_extra_defaults && !defaults_already_read) { diff --git a/mysys/my_lib.c b/mysys/my_lib.c index 9c465fd5e68..5ab3facc348 100644 --- a/mysys/my_lib.c +++ b/mysys/my_lib.c @@ -119,10 +119,6 @@ MY_DIR *my_dir(const char *path, myf MyFlags) DBUG_ENTER("my_dir"); DBUG_PRINT("my",("path: '%s' MyFlags: %lu",path,MyFlags)); -#if !defined(HAVE_READDIR_R) - mysql_mutex_lock(&THR_LOCK_open); -#endif - tmp_file= directory_file_name(tmp_path, path); if (!(dirp= opendir(tmp_path))) @@ -174,9 +170,6 @@ MY_DIR *my_dir(const char *path, myf MyFlags) } (void) closedir(dirp); -#if !defined(HAVE_READDIR_R) - mysql_mutex_unlock(&THR_LOCK_open); -#endif if (MyFlags & MY_WANT_SORT) sort_dynamic(&dirh->array, (qsort_cmp) comp_names); @@ -187,9 +180,6 @@ MY_DIR *my_dir(const char *path, myf MyFlags) DBUG_RETURN(&dirh->dir); error: -#if !defined(HAVE_READDIR_R) - mysql_mutex_unlock(&THR_LOCK_open); -#endif my_errno=errno; if (dirp) (void) closedir(dirp); diff --git a/mysys/my_thr_init.c b/mysys/my_thr_init.c index 678bfc459c7..3f9c8eeba10 100644 --- a/mysys/my_thr_init.c +++ b/mysys/my_thr_init.c @@ -385,7 +385,6 @@ void my_thread_end(void) /* Trash variable so that we can detect false accesses to my_thread_var */ tmp->init= 2; - TRASH(tmp, sizeof(*tmp)); free(tmp); } } diff --git a/mysys_ssl/my_crypt.cc b/mysys_ssl/my_crypt.cc index 92f4012d175..db303f37b0e 100644 --- a/mysys_ssl/my_crypt.cc +++ b/mysys_ssl/my_crypt.cc @@ -323,24 +323,11 @@ unsigned int my_aes_ctx_size(enum my_aes_mode) return MY_AES_CTX_SIZE; } -#ifdef HAVE_YASSL -#include <random.hpp> -int my_random_bytes(uchar* buf, int num) -{ - TaoCrypt::RandomNumberGenerator rand; - rand.GenerateBlock((TaoCrypt::byte*) buf, num); - return MY_AES_OK; -} -#else - int my_random_bytes(uchar *buf, int num) { - RAND_METHOD *rand = RAND_OpenSSL(); - if (rand == NULL || rand->bytes(buf, num) != 1) + if (RAND_bytes(buf, num) != 1) return MY_AES_OPENSSL_ERROR; return MY_AES_OK; } -#endif } - diff --git a/mysys_ssl/openssl.c b/mysys_ssl/openssl.c index 3f841eec92f..f3dc8f4277c 100644 --- a/mysys_ssl/openssl.c +++ b/mysys_ssl/openssl.c @@ -51,7 +51,7 @@ int check_openssl_compatibility() EVP_MD_CTX *md5_ctx; if (!CRYPTO_set_mem_functions(coc_malloc, NULL, NULL)) - return 1; + return 0; testing= 1; alloc_size= alloc_count= 0; diff --git a/mysys_ssl/yassl.cc b/mysys_ssl/yassl.cc index 23376c82b4f..4e9c21ebfd1 100644 --- a/mysys_ssl/yassl.cc +++ b/mysys_ssl/yassl.cc @@ -26,6 +26,7 @@ #include "aes.hpp" using yaSSL::yaERR_remove_state; +using yaSSL::yaRAND_bytes; #define EVP_CIPH_ECB_MODE 0x1U #define EVP_CIPH_CBC_MODE 0x2U diff --git a/plugin/auth_gssapi/mysql-test/auth_gssapi/basic.result b/plugin/auth_gssapi/mysql-test/auth_gssapi/basic.result index dc5155fac8c..b7cf3d8e488 100644 --- a/plugin/auth_gssapi/mysql-test/auth_gssapi/basic.result +++ b/plugin/auth_gssapi/mysql-test/auth_gssapi/basic.result @@ -1,16 +1,24 @@ INSTALL SONAME 'auth_gssapi'; +Warnings: +Note 1105 SSPI: using principal name 'localhost', mech 'Negotiate' CREATE USER 'GSSAPI_SHORTNAME' IDENTIFIED WITH gssapi; +connect con1,localhost,$GSSAPI_SHORTNAME,,; SELECT USER(),CURRENT_USER(); USER() CURRENT_USER() GSSAPI_SHORTNAME@localhost GSSAPI_SHORTNAME@% +disconnect con1; +connection default; DROP USER 'GSSAPI_SHORTNAME'; CREATE USER nosuchuser IDENTIFIED WITH gssapi; ERROR 28000: GSSAPI name mismatch, requested 'nosuchuser', actual name 'GSSAPI_SHORTNAME' DROP USER nosuchuser; CREATE USER usr1 IDENTIFIED WITH gssapi as 'GSSAPI_FULLNAME'; +connect con1,localhost,usr1,,; SELECT USER(),CURRENT_USER(); USER() CURRENT_USER() usr1@localhost usr1@% +disconnect con1; +connection default; DROP USER usr1; CREATE USER nosuchuser IDENTIFIED WITH gssapi AS 'nosuchuser@EXAMPLE.COM'; ERROR 28000: GSSAPI name mismatch, requested 'nosuchuser@EXAMPLE.COM', actual name 'GSSAPI_FULLNAME' diff --git a/plugin/auth_gssapi/sspi_server.cc b/plugin/auth_gssapi/sspi_server.cc index d2c2ae7e4b9..44ab091771f 100644 --- a/plugin/auth_gssapi/sspi_server.cc +++ b/plugin/auth_gssapi/sspi_server.cc @@ -284,7 +284,7 @@ int plugin_init() { srv_principal_name= get_default_principal_name(); } - my_printf_error(0, "SSPI: using principal name '%s', mech '%s'", + my_printf_error(ER_UNKNOWN_ERROR, "SSPI: using principal name '%s', mech '%s'", ME_ERROR_LOG | ME_NOTE, srv_principal_name, srv_mech_name); ret = AcquireCredentialsHandle( diff --git a/plugin/server_audit/server_audit.c b/plugin/server_audit/server_audit.c index e2097b58a17..aea3a9dfcc5 100644 --- a/plugin/server_audit/server_audit.c +++ b/plugin/server_audit/server_audit.c @@ -1237,7 +1237,7 @@ static int write_log(const char *message, size_t len) if (output_type == OUTPUT_FILE) { if (logfile && - (is_active= (logger_write(logfile, message, len) == len))) + (is_active= (logger_write(logfile, message, len) == (int)len))) return 0; ++log_write_failures; return 1; diff --git a/scripts/galera_recovery.sh b/scripts/galera_recovery.sh index de2e653c497..09de6721762 100644 --- a/scripts/galera_recovery.sh +++ b/scripts/galera_recovery.sh @@ -68,7 +68,7 @@ parse_arguments() { wsrep_recover_position() { # Redirect server's error log to the log file. - eval /usr/sbin/mysqld $cmdline_args --user=$user --wsrep_recover \ + eval @sbindir@/mysqld $cmdline_args --user=$user --wsrep_recover \ --disable-log-error 2> "$log_file" ret=$? if [ $ret -ne 0 ]; then diff --git a/scripts/mysql_install_db.sh b/scripts/mysql_install_db.sh index 07565f7046d..a84b8287e9e 100644 --- a/scripts/mysql_install_db.sh +++ b/scripts/mysql_install_db.sh @@ -27,6 +27,7 @@ srcdir="" args="" defaults="" +defaults_group_suffix="" mysqld_opt="" user="" silent_startup="--silent-startup" @@ -65,6 +66,9 @@ Usage: $0 [OPTIONS] --defaults-extra-file=name Read this file after the global files are read. --defaults-file=name Only read default options from the given file name. + --defaults-group-suffix=name + In addition to the given groups, read also groups with + this suffix --force Causes mysql_install_db to run even if DNS does not work. In that case, grant table entries that normally use hostnames will use IP addresses. @@ -147,6 +151,8 @@ parse_arguments() --help) usage ;; --no-defaults|--defaults-file=*|--defaults-extra-file=*) defaults="$arg" ;; + --defaults-group-suffix=*) + defaults_group_suffix="$arg" ;; --cross-bootstrap|--windows) # Used when building the MariaDB system tables on a different host than @@ -288,7 +294,7 @@ fi # Now we can get arguments from the groups [mysqld] and [mysql_install_db] # in the my.cfg file, then re-run to merge with command line arguments. -parse_arguments `"$print_defaults" $defaults --mysqld mysql_install_db` +parse_arguments `"$print_defaults" $defaults $defaults_group_suffix --mysqld mysql_install_db` parse_arguments PICK-ARGS-FROM-ARGV "$@" # Configure paths to support files @@ -452,7 +458,7 @@ fi mysqld_bootstrap="${MYSQLD_BOOTSTRAP-$mysqld}" mysqld_install_cmd_line() { - "$mysqld_bootstrap" $defaults "$mysqld_opt" --bootstrap $silent_startup\ + "$mysqld_bootstrap" $defaults $defaults_group_suffix "$mysqld_opt" --bootstrap $silent_startup\ "--basedir=$basedir" "--datadir=$ldata" --log-warnings=0 --enforce-storage-engine="" \ $args --max_allowed_packet=8M \ --net_buffer_length=16K @@ -486,7 +492,7 @@ else echo echo "You can also try to start the mysqld daemon with:" echo - echo " shell> $mysqld --skip-grant --general-log &" + echo " shell> $mysqld --skip-grant-tables --general-log &" echo echo "and use the command line tool $bindir/mysql" echo "to connect to the mysql database and look at the grant tables:" @@ -497,8 +503,8 @@ else echo "Try 'mysqld --help' if you have problems with paths. Using" echo "--general-log gives you a log in $ldata that may be helpful." link_to_help - echo "MariaDB is hosted on launchpad; You can find the latest source and" - echo "email lists at http://launchpad.net/maria" + echo "You can find the latest source at https://downloads.mariadb.org and" + echo "the maria-discuss email list at https://launchpad.net/~maria-discuss" echo echo "Please check all of the above before submitting a bug report" echo "at http://mariadb.org/jira" diff --git a/scripts/wsrep_sst_common.sh b/scripts/wsrep_sst_common.sh index 3cd2d0e2053..edf7b2d71aa 100755 --- a/scripts/wsrep_sst_common.sh +++ b/scripts/wsrep_sst_common.sh @@ -20,13 +20,13 @@ set -u WSREP_SST_OPT_BYPASS=0 WSREP_SST_OPT_BINLOG="" -WSREP_SST_OPT_CONF_SUFFIX="" WSREP_SST_OPT_DATA="" WSREP_SST_OPT_AUTH=${WSREP_SST_OPT_AUTH:-} WSREP_SST_OPT_USER=${WSREP_SST_OPT_USER:-} WSREP_SST_OPT_PSWD=${WSREP_SST_OPT_PSWD:-} WSREP_SST_OPT_DEFAULT="" WSREP_SST_OPT_EXTRA_DEFAULT="" +WSREP_SST_OPT_SUFFIX_DEFAULT="" while [ $# -gt 0 ]; do case "$1" in @@ -35,19 +35,16 @@ case "$1" in # # Break address string into host:port/path parts # - if echo $WSREP_SST_OPT_ADDR | grep -qe '^\[.*\]' - then - # IPv6 notation - readonly WSREP_SST_OPT_HOST=${WSREP_SST_OPT_ADDR/\]*/\]} - readonly WSREP_SST_OPT_HOST_UNESCAPED=$(echo $WSREP_SST_OPT_HOST | \ - cut -d '[' -f 2 | cut -d ']' -f 1) - else - # "traditional" notation - readonly WSREP_SST_OPT_HOST=${WSREP_SST_OPT_ADDR%%[:/]*} - fi + readonly WSREP_SST_OPT_HOST=${WSREP_SST_OPT_ADDR%%[:/]*} + readonly WSREP_SST_OPT_HOST_UNESCAPED=`echo "$WSREP_SST_OPT_HOST"|awk '{if(match($0,/^\[.*\]$/)) $0=substr($0,2,RLENGTH-2);print}'` readonly WSREP_SST_OPT_ADDR_PORT=$(echo $WSREP_SST_OPT_ADDR | \ cut -d ']' -f 2 | cut -s -d ':' -f 2 | cut -d '/' -f 1) readonly WSREP_SST_OPT_PATH=${WSREP_SST_OPT_ADDR#*/} + readonly WSREP_SST_OPT_MODULE=${WSREP_SST_OPT_PATH%%/*} + remain=${WSREP_SST_OPT_PATH#*/} + readonly WSREP_SST_OPT_LSN=${remain%%/*} + remain=${remain#*/} + readonly WSREP_SST_OPT_SST_VER=${remain%%/*} shift ;; '--bypass') @@ -66,7 +63,7 @@ case "$1" in shift ;; '--defaults-group-suffix') - WSREP_SST_OPT_CONF_SUFFIX="$2" + readonly WSREP_SST_OPT_SUFFIX_DEFAULT="$1=$2" shift ;; '--host') @@ -122,7 +119,6 @@ shift done readonly WSREP_SST_OPT_BYPASS readonly WSREP_SST_OPT_BINLOG -readonly WSREP_SST_OPT_CONF_SUFFIX if [ -n "${WSREP_SST_OPT_ADDR:-}" ]; then if [ -n "${WSREP_SST_OPT_PORT:-}" ]; then @@ -161,19 +157,18 @@ else MY_PRINT_DEFAULTS=$(which my_print_defaults) fi -readonly WSREP_SST_OPT_CONF="$WSREP_SST_OPT_DEFAULT $WSREP_SST_OPT_EXTRA_DEFAULT" -MY_PRINT_DEFAULTS="$MY_PRINT_DEFAULTS $WSREP_SST_OPT_CONF" +readonly WSREP_SST_OPT_CONF="$WSREP_SST_OPT_DEFAULT $WSREP_SST_OPT_EXTRA_DEFAULT $WSREP_SST_OPT_SUFFIX_DEFAULT" +readonly MY_PRINT_DEFAULTS="$MY_PRINT_DEFAULTS $WSREP_SST_OPT_CONF" + wsrep_auth_not_set() { [ -z "$WSREP_SST_OPT_AUTH" -o "$WSREP_SST_OPT_AUTH" = "(null)" ] } -# For Bug:1200727 -if $MY_PRINT_DEFAULTS sst | grep -q "wsrep_sst_auth" -then - if wsrep_auth_not_set - then - WSREP_SST_OPT_AUTH=$($MY_PRINT_DEFAULTS sst | grep -- "--wsrep_sst_auth" | cut -d= -f2) +# State Snapshot Transfer authentication password was displayed in the ps output. Bug fixed #1200727. +if $MY_PRINT_DEFAULTS sst | grep -q "wsrep_sst_auth"; then + if wsrep_auth_not_set; then + WSREP_SST_OPT_AUTH=$($MY_PRINT_DEFAULTS sst | grep -- "--wsrep_sst_auth" | cut -d= -f2) fi fi readonly WSREP_SST_OPT_AUTH @@ -251,7 +246,7 @@ wsrep_check_programs() # process like encryption, etc..... # parse such configuration option. (group for xb settings is [sst] in my.cnf # -# 1st param: group : name of the config file section, e.g. mysqld +# 1st param: group (config file section like sst) or my_print_defaults argument (like --mysqld) # 2nd param: var : name of the variable in the section, e.g. server-id # 3rd param: - : default value for the param parse_cnf() @@ -260,20 +255,11 @@ parse_cnf() local var=$2 local reval="" - # print the default settings for given group using my_print_default. # normalize the variable names specified in cnf file (user can use _ or - for example log-bin or log_bin) - # then grep for needed variable + # then search for needed variable # finally get the variable value (if variables has been specified multiple time use the last value only) - # look in group+suffix - if [ -n $WSREP_SST_OPT_CONF_SUFFIX ]; then - reval=$($MY_PRINT_DEFAULTS "${group}${WSREP_SST_OPT_CONF_SUFFIX}" | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2- | tail -1) - fi - - # look in group - if [ -z $reval ]; then - reval=$($MY_PRINT_DEFAULTS $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2- | tail -1) - fi + reval=$($MY_PRINT_DEFAULTS "${group}" | awk -v var="${var}" 'BEGIN { OFS=FS="=" } { gsub(/_/,"-",$1); if ( $1=="--"var) lastval=substr($0,length($1)+2) } END { print lastval}') # use default if we haven't found a value if [ -z $reval ]; then diff --git a/scripts/wsrep_sst_mysqldump.sh b/scripts/wsrep_sst_mysqldump.sh index 8cfdd4e6553..d28a1c161ce 100644 --- a/scripts/wsrep_sst_mysqldump.sh +++ b/scripts/wsrep_sst_mysqldump.sh @@ -17,10 +17,6 @@ # This is a reference script for mysqldump-based state snapshot tansfer -# This variable is not used in mysqldump sst, so better initialize it -# to avoid shell's "parameter not set" message. -WSREP_SST_OPT_CONF="" - . $(dirname $0)/wsrep_sst_common PATH=$PATH:/usr/sbin:/usr/bin:/sbin:/bin @@ -57,10 +53,10 @@ then fi # Check client version -if ! $MYSQL_CLIENT --version | grep 'Distrib 10.' >/dev/null +if ! $MYSQL_CLIENT --version | grep 'Distrib 10\.[1-9]' >/dev/null then $MYSQL_CLIENT --version >&2 - wsrep_log_error "this operation requires MySQL client version 10 or newer" + wsrep_log_error "this operation requires MySQL client version 10.1 or newer" exit $EINVAL fi @@ -118,7 +114,7 @@ $MYSQL_CLIENT $AUTH -S$WSREP_SST_OPT_SOCKET --disable-reconnect --connect_timeou tail -1 | awk -F ' ' '{ print $2 }') MYSQL="$MYSQL_CLIENT $WSREP_SST_OPT_CONF "\ -"$AUTH -h${WSREP_SST_OPT_HOST_UNESCAPED:-$WSREP_SST_OPT_HOST} "\ +"$AUTH -h${WSREP_SST_OPT_HOST_UNESCAPED} "\ "-P$WSREP_SST_OPT_PORT --disable-reconnect --connect_timeout=10" # Check if binary logging is enabled on the joiner node. diff --git a/scripts/wsrep_sst_rsync.sh b/scripts/wsrep_sst_rsync.sh index 24720ff3587..05c99880d75 100644 --- a/scripts/wsrep_sst_rsync.sh +++ b/scripts/wsrep_sst_rsync.sh @@ -135,19 +135,7 @@ fi WSREP_LOG_DIR=${WSREP_LOG_DIR:-""} # if WSREP_LOG_DIR env. variable is not set, try to get it from my.cnf if [ -z "$WSREP_LOG_DIR" ]; then - WSREP_LOG_DIR=$(parse_cnf mariadb-10.0 innodb_log_group_home_dir "") -fi -if [ -z "$WSREP_LOG_DIR" ]; then - WSREP_LOG_DIR=$(parse_cnf mysqld innodb_log_group_home_dir "") -fi -if [ -z "$WSREP_LOG_DIR" ]; then - WSREP_LOG_DIR=$(parse_cnf server innodb_log_group_home_dir "") -fi -if [ -z "$WSREP_LOG_DIR" ]; then - WSREP_LOG_DIR=$(parse_cnf mariadb innodb_log_group_home_dir "") -fi -if [ -z "$WSREP_LOG_DIR" ]; then - WSREP_LOG_DIR=$(parse_cnf mysqld-10.0 innodb_log_group_home_dir "") + WSREP_LOG_DIR=$(parse_cnf --mysqld innodb-log-group-home-dir '') fi if [ -n "$WSREP_LOG_DIR" ]; then diff --git a/scripts/wsrep_sst_xtrabackup-v2.sh b/scripts/wsrep_sst_xtrabackup-v2.sh index 9284bf78019..64dd182e2f2 100644 --- a/scripts/wsrep_sst_xtrabackup-v2.sh +++ b/scripts/wsrep_sst_xtrabackup-v2.sh @@ -32,9 +32,6 @@ ecode=0 ssyslog="" ssystag="" XTRABACKUP_PID="" -SST_PORT="" -REMOTEIP="" -REMOTEHOST="" tca="" tcert="" tkey="" @@ -42,7 +39,6 @@ sockopt="" progress="" ttime=0 totime=0 -lsn="" ecmd="" rlimit="" # Initially @@ -77,11 +73,6 @@ ssl_cert="" ssl_ca="" ssl_key="" -# Required for backup locks -# For backup locks it is 1 sent by joiner -# 5.6.21 PXC and later can't donate to an older joiner -sst_ver=1 - if which pv &>/dev/null && pv --help | grep -q FORMAT;then pvopts+=$pvformat fi @@ -97,6 +88,13 @@ MAGIC_FILE="${DATA}/${INFO_FILE}" # Setting the path for ss and ip export PATH="/usr/sbin:/sbin:$PATH" +OS=$(uname) + +if ! which lsof > /dev/null; then + wsrep_log_error "lsof tool not found in PATH! Make sure you have it installed." + exit 2 # ENOENT +fi + timeit(){ local stage=$1 shift @@ -251,11 +249,7 @@ verify_file_exists() get_transfer() { - if [[ -z $SST_PORT ]];then - TSST_PORT=4444 - else - TSST_PORT=$SST_PORT - fi + TSST_PORT=${WSREP_SST_OPT_PORT:-4444} if [[ $tfmt == 'nc' ]];then if [[ ! -x `which nc` ]];then @@ -280,7 +274,7 @@ get_transfer() fi else # netcat doesn't understand [] around IPv6 address - tcmd="nc ${REMOTEIP//[\[\]]/} ${TSST_PORT}" + tcmd="nc ${WSREP_SST_OPT_HOST_UNESCAPED} ${TSST_PORT}" fi else tfmt='socat' @@ -342,7 +336,7 @@ get_transfer() tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=${tcert},cafile=${tca}${joiner_extra}${sockopt} stdio" else wsrep_log_info "Encrypting with CERT: $tcert, CA: $tca" - tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=${tcert},cafile=${tca}${donor_extra}${sockopt}" + tcmd="socat -u stdio openssl-connect:${WSREP_SST_OPT_HOST}:${TSST_PORT},cert=${tcert},cafile=${tca}${donor_extra}${sockopt}" fi elif [[ $encrypt -eq 3 ]];then wsrep_log_warning "**** WARNING **** encrypt=3 is deprecated and will be removed in a future release" @@ -359,7 +353,7 @@ get_transfer() tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=${tcert},key=${tkey},verify=0${joiner_extra}${sockopt} stdio" else wsrep_log_info "Encrypting with CERT: $tcert, KEY: $tkey" - tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=${tcert},key=${tkey},verify=0${sockopt}" + tcmd="socat -u stdio openssl-connect:${WSREP_SST_OPT_HOST}:${TSST_PORT},cert=${tcert},key=${tkey},verify=0${sockopt}" fi elif [[ $encrypt -eq 4 ]]; then wsrep_log_info "Using openssl based encryption with socat: with key, crt, and ca" @@ -380,7 +374,7 @@ get_transfer() tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=${ssl_cert},key=${ssl_key},cafile=${ssl_ca},verify=1${joiner_extra}${sockopt} stdio" else wsrep_log_info "Encrypting with CERT: $ssl_cert, KEY: $ssl_key, CA: $ssl_ca" - tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=${ssl_cert},key=${ssl_key},cafile=${ssl_ca},verify=1${donor_extra}${sockopt}" + tcmd="socat -u stdio openssl-connect:${WSREP_SST_OPT_HOST}:${TSST_PORT},cert=${ssl_cert},key=${ssl_key},cafile=${ssl_ca},verify=1${donor_extra}${sockopt}" fi else @@ -391,7 +385,7 @@ get_transfer() if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]]; then tcmd="socat -u TCP-LISTEN:${TSST_PORT},reuseaddr${sockopt} stdio" else - tcmd="socat -u stdio TCP:${REMOTEIP}:${TSST_PORT}${sockopt}" + tcmd="socat -u stdio TCP:${WSREP_SST_OPT_HOST}:${TSST_PORT}${sockopt}" fi fi fi @@ -400,7 +394,7 @@ get_transfer() get_footprint() { pushd $WSREP_SST_OPT_DATA 1>/dev/null - payload=$(find . -regex '.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' -type f -print0 | du --files0-from=- --block-size=1 -c | awk 'END { print $1 }') + payload=$(find . -regex '.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' -type f -print0 | du --files0-from=- --block-size=1 -c -s | awk 'END { print $1 }') if $MY_PRINT_DEFAULTS xtrabackup | grep -q -- "--compress";then # QuickLZ has around 50% compression ratio # When compression/compaction used, the progress is only an approximate. @@ -452,7 +446,11 @@ read_cnf() progress=$(parse_cnf sst progress "") rebuild=$(parse_cnf sst rebuild 0) ttime=$(parse_cnf sst time 0) - cpat=$(parse_cnf sst cpat '.*\.pem$\|.*init\.ok$\|.*galera\.cache$\|.*sst_in_progress$\|.*\.sst$\|.*gvwstate\.dat$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$') + if [ "${OS}" = "FreeBSD" ]; then + cpat=$(parse_cnf sst cpat '.*\.pem$|.*init\.ok$|.*galera\.cache$|.*sst_in_progress$|.*\.sst$|.*gvwstate\.dat$|.*grastate\.dat$|.*\.err$|.*\.log$|.*RPM_UPGRADE_MARKER$|.*RPM_UPGRADE_HISTORY$') + else + cpat=$(parse_cnf sst cpat '.*\.pem$\|.*init\.ok$\|.*galera\.cache$\|.*sst_in_progress$\|.*\.sst$\|.*gvwstate\.dat$\|.*grastate\.dat$\|.*\.err$\|.*\.log$\|.*RPM_UPGRADE_MARKER$\|.*RPM_UPGRADE_HISTORY$') + fi ealgo=$(parse_cnf xtrabackup encrypt "") ekey=$(parse_cnf xtrabackup encrypt-key "") ekeyfile=$(parse_cnf xtrabackup encrypt-key-file "") @@ -470,15 +468,15 @@ read_cnf() # Pull the parameters needed for encrypt=4 ssl_ca=$(parse_cnf sst ssl-ca "") if [[ -z "$ssl_ca" ]]; then - ssl_ca=$(parse_cnf mysqld ssl-ca "") + ssl_ca=$(parse_cnf --mysqld ssl-ca "") fi ssl_cert=$(parse_cnf sst ssl-cert "") if [[ -z "$ssl_cert" ]]; then - ssl_cert=$(parse_cnf mysqld ssl-cert "") + ssl_cert=$(parse_cnf --mysqld ssl-cert "") fi ssl_key=$(parse_cnf sst ssl-key "") if [[ -z "$ssl_key" ]]; then - ssl_key=$(parse_cnf mysqld ssl-key "") + ssl_key=$(parse_cnf --mysqld ssl-key "") fi rlimit=$(parse_cnf sst rlimit "") @@ -492,7 +490,7 @@ read_cnf() ssystag+="-" if [[ $ssyslog -ne -1 ]];then - if $MY_PRINT_DEFAULTS mysqld_safe | tr '_' '-' | grep -q -- "--syslog";then + if $MY_PRINT_DEFAULTS mysqld_safe | grep -q -- "--syslog";then ssyslog=1 fi fi @@ -635,18 +633,6 @@ kill_xtrabackup() rm -f "$XTRABACKUP_PID" || true } -setup_ports() -{ - if [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then - SST_PORT=$WSREP_SST_OPT_PORT - REMOTEIP=$WSREP_SST_OPT_HOST - lsn=$(echo $WSREP_SST_OPT_PATH | awk -F '[/]' '{ print $2 }') - sst_ver=$(echo $WSREP_SST_OPT_PATH | awk -F '[/]' '{ print $3 }') - else - SST_PORT=$WSREP_SST_OPT_PORT - fi -} - # waits ~1 minute for nc/socat to open the port and then reports ready # (regardless of timeout) wait_for_listen() @@ -654,22 +640,24 @@ wait_for_listen() local HOST=$1 local PORT=$2 local MODULE=$3 + local LSOF_OUT for i in {1..300} do - ss -p state listening "( sport = :$PORT )" | grep -qE 'socat|nc' && break + LSOF_OUT=$(lsof -sTCP:LISTEN -i TCP:${PORT} -a -c nc -c socat -F c) + [ -n "${LSOF_OUT}" ] && break sleep 0.2 done - echo "ready ${HOST}:${PORT}/${MODULE}//$sst_ver" + echo "ready ${HOST}:${PORT}/${MODULE}//${WSREP_SST_OPT_SST_VER:-1}" } check_extra() { local use_socket=1 if [[ $uextra -eq 1 ]];then - if $MY_PRINT_DEFAULTS --mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then - local eport=$($MY_PRINT_DEFAULTS mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2) + if [ $(parse_cnf --mysqld thread-handling) = 'pool-of-threads'];then + local eport=$(parse_cnf --mysqld extra-port) if [[ -n $eport ]];then # Xtrabackup works only locally. # Hence, setting host to 127.0.0.1 unconditionally. @@ -830,7 +818,6 @@ if [[ ! ${WSREP_SST_OPT_ROLE} == 'joiner' && ! ${WSREP_SST_OPT_ROLE} == 'donor' fi read_cnf -setup_ports if ${INNOBACKUPEX_BIN} /tmp --help 2>/dev/null | grep -q -- '--version-check'; then disver="--no-version-check" @@ -864,20 +851,24 @@ if [[ $ssyslog -eq 1 ]];then logger -p daemon.info -t ${ssystag}wsrep-sst-$WSREP_SST_OPT_ROLE "$@" } - INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} 2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-apply " - INNOMOVE="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_DEFAULT} $disver $impts --datadir=${DATA} --move-back --force-non-empty-directories \${DATA} 2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-move " - INNOBACKUP="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_DEFAULT} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir 2> >(logger -p daemon.err -t ${ssystag}innobackupex-backup)" + INNOAPPLY="2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-apply " + INNOMOVE="2>&1 | logger -p daemon.err -t ${ssystag}innobackupex-move " + INNOBACKUP="2> >(logger -p daemon.err -t ${ssystag}innobackupex-backup)" fi else - INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} &>\${DATA}/innobackup.prepare.log" - INNOMOVE="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_DEFAULT} --defaults-group=mysqld${WSREP_SST_OPT_CONF_SUFFIX} $disver $impts --datadir=${DATA} --move-back --force-non-empty-directories \${DATA} &>\${DATA}/innobackup.move.log" - INNOBACKUP="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_DEFAULT} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir 2>\${DATA}/innobackup.backup.log" + INNOAPPLY="&>\${DATA}/innobackup.prepare.log" + INNOMOVE="&>\${DATA}/innobackup.move.log" + INNOBACKUP="2>\${DATA}/innobackup.backup.log" fi get_stream get_transfer +INNOAPPLY="${INNOBACKUPEX_BIN} $disver $iapts --apply-log \$rebuildcmd \${DATA} ${INNOAPPLY}" +INNOMOVE="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} $disver $impts --move-back --force-non-empty-directories \${DATA} ${INNOMOVE}" +INNOBACKUP="${INNOBACKUPEX_BIN} ${WSREP_SST_OPT_CONF} $disver $iopts \$tmpopts \$INNOEXTRA --galera-info --stream=\$sfmt \$itmpdir ${INNOBACKUP}" + if [ "$WSREP_SST_OPT_ROLE" = "donor" ] then trap cleanup_donor EXIT @@ -885,13 +876,13 @@ then if [ $WSREP_SST_OPT_BYPASS -eq 0 ] then usrst=0 - if [[ -z $sst_ver ]];then + if [[ -z $WSREP_SST_OPT_SST_VER ]];then wsrep_log_error "Upgrade joiner to 5.6.21 or higher for backup locks support" wsrep_log_error "The joiner is not supported for this version of donor" exit 93 fi - if [[ -z $(parse_cnf mysqld tmpdir "") && -z $(parse_cnf xtrabackup tmpdir "") ]];then + if [[ -z $(parse_cnf --mysqld tmpdir "") && -z $(parse_cnf xtrabackup tmpdir "") ]];then xtmpdir=$(mktemp -d) tmpopts=" --tmpdir=$xtmpdir " wsrep_log_info "Using $xtmpdir as xtrabackup temporary directory" @@ -948,7 +939,7 @@ then wsrep_log_info "Sleeping before data transfer for SST" sleep 10 - wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${SST_PORT:-4444}" + wsrep_log_info "Streaming the backup to joiner at ${WSREP_SST_OPT_HOST} ${WSREP_SST_OPT_PORT:-4444}" # Add compression to the head of the stream (if specified) if [[ -n $scomp ]]; then @@ -1010,9 +1001,9 @@ then [[ -e $SST_PROGRESS_FILE ]] && wsrep_log_info "Stale sst_in_progress file: $SST_PROGRESS_FILE" [[ -n $SST_PROGRESS_FILE ]] && touch $SST_PROGRESS_FILE - ib_home_dir=$(parse_cnf mysqld innodb-data-home-dir "") - ib_log_dir=$(parse_cnf mysqld innodb-log-group-home-dir "") - ib_undo_dir=$(parse_cnf mysqld innodb-undo-directory "") + ib_home_dir=$(parse_cnf --mysqld innodb-data-home-dir "") + ib_log_dir=$(parse_cnf --mysqld innodb-log-group-home-dir "") + ib_undo_dir=$(parse_cnf --mysqld innodb-undo-directory "") stagemsg="Joiner-Recv" @@ -1072,9 +1063,13 @@ then wsrep_log_info "Cleaning the existing datadir and innodb-data/log directories" - find $ib_home_dir $ib_log_dir $ib_undo_dir $DATA -mindepth 1 -prune -regex $cpat -o -exec rm -rfv {} 1>&2 \+ + if [ "${OS}" = "FreeBSD" ]; then + find -E $ib_home_dir $ib_log_dir $ib_undo_dir $DATA -mindepth 1 -prune -regex $cpat -o -exec rm -rfv {} 1>&2 \+ + else + find $ib_home_dir $ib_log_dir $ib_undo_dir $DATA -mindepth 1 -prune -regex $cpat -o -exec rm -rfv {} 1>&2 \+ + fi - tempdir=$(parse_cnf mysqld log-bin "") + tempdir=$(parse_cnf --mysqld log-bin "") if [[ -n ${tempdir:-} ]];then binlog_dir=$(dirname $tempdir) binlog_file=$(basename $tempdir) diff --git a/scripts/wsrep_sst_xtrabackup.sh b/scripts/wsrep_sst_xtrabackup.sh index ca3c0129837..867aab622ed 100644 --- a/scripts/wsrep_sst_xtrabackup.sh +++ b/scripts/wsrep_sst_xtrabackup.sh @@ -30,15 +30,13 @@ encrypt=0 nproc=1 ecode=0 XTRABACKUP_PID="" -SST_PORT="" -REMOTEIP="" tcert="" tpem="" sockopt="" progress="" ttime=0 totime=0 -lsn="" +lsn="${WSREP_SST_OPT_LSN}" incremental=0 ecmd="" rlimit="" @@ -136,11 +134,7 @@ get_keys() get_transfer() { - if [[ -z $SST_PORT ]];then - TSST_PORT=4444 - else - TSST_PORT=$SST_PORT - fi + TSST_PORT=${WSREP_SST_OPT_PORT:-4444} if [[ $tfmt == 'nc' ]];then if [[ ! -x `which nc` ]];then @@ -155,7 +149,7 @@ get_transfer() tcmd="nc -dl ${TSST_PORT}" fi else - tcmd="nc ${REMOTEIP} ${TSST_PORT}" + tcmd="nc ${WSREP_SST_OPT_HOST_UNESCAPED} ${TSST_PORT}" fi else tfmt='socat' @@ -181,34 +175,23 @@ get_transfer() tcmd="socat -u openssl-listen:${TSST_PORT},reuseaddr,cert=$tpem,cafile=${tcert}${sockopt} stdio" else wsrep_log_info "Encrypting with PEM $tpem, CA: $tcert" - tcmd="socat -u stdio openssl-connect:${REMOTEIP}:${TSST_PORT},cert=$tpem,cafile=${tcert}${sockopt}" + tcmd="socat -u stdio openssl-connect:${WSREP_SST_OPT_HOST}:${TSST_PORT},cert=$tpem,cafile=${tcert}${sockopt}" fi else if [[ "$WSREP_SST_OPT_ROLE" == "joiner" ]];then tcmd="socat -u TCP-LISTEN:${TSST_PORT},reuseaddr${sockopt} stdio" else - tcmd="socat -u stdio TCP:${REMOTEIP}:${TSST_PORT}${sockopt}" + tcmd="socat -u stdio TCP:${WSREP_SST_OPT_HOST}:${TSST_PORT}${sockopt}" fi fi fi } -parse_cnf() -{ - local group=$1 - local var=$2 - reval=$($MY_PRINT_DEFAULTS $group | awk -F= '{if ($1 ~ /_/) { gsub(/_/,"-",$1); print $1"="$2 } else { print $0 }}' | grep -- "--$var=" | cut -d= -f2-) - if [[ -z $reval ]];then - [[ -n $3 ]] && reval=$3 - fi - echo $reval -} - get_footprint() { pushd $WSREP_SST_OPT_DATA 1>/dev/null - payload=$(find . -regex '.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' -type f -print0 | du --files0-from=- --block-size=1 -c | awk 'END { print $1 }') + payload=$(find . -regex '.*\.ibd$\|.*\.MYI$\|.*\.MYD$\|.*ibdata1$' -type f -print0 | du --files0-from=- --block-size=1 -c -s | awk 'END { print $1 }') if $MY_PRINT_DEFAULTS xtrabackup | grep -q -- "--compress";then # QuickLZ has around 50% compression ratio # When compression/compaction used, the progress is only an approximate. @@ -354,17 +337,6 @@ kill_xtrabackup() rm -f "$XTRABACKUP_PID" } -setup_ports() -{ - if [[ "$WSREP_SST_OPT_ROLE" == "donor" ]];then - SST_PORT=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $2 }') - REMOTEIP=$(echo $WSREP_SST_OPT_ADDR | awk -F ':' '{ print $1 }') - lsn=$(echo $WSREP_SST_OPT_ADDR | awk -F '[:/]' '{ print $4 }') - else - SST_PORT=$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $2 }') - fi -} - # waits ~10 seconds for nc to open the port and then reports ready # (regardless of timeout) wait_for_listen() @@ -388,8 +360,8 @@ check_extra() { local use_socket=1 if [[ $uextra -eq 1 ]];then - if $MY_PRINT_DEFAULTS --mysqld | tr '_' '-' | grep -- "--thread-handling=" | grep -q 'pool-of-threads';then - local eport=$($MY_PRINT_DEFAULTS --mysqld | tr '_' '-' | grep -- "--extra-port=" | cut -d= -f2) + if [ $(parse_cnf --mysqld thread-handling) = 'pool-of-threads'];then + local eport=$(parse_cnf --mysqld extra-port) if [[ -n $eport ]];then # Xtrabackup works only locally. # Hence, setting host to 127.0.0.1 unconditionally. @@ -466,7 +438,7 @@ then check_extra - wsrep_log_info "Streaming the backup to joiner at ${REMOTEIP} ${SST_PORT}" + wsrep_log_info "Streaming the backup to joiner at ${WSREP_SST_OPT_HOST} ${WSREP_SST_OPT_PORT}" if [[ -n $progress ]];then get_footprint @@ -547,14 +519,9 @@ then # May need xtrabackup_checkpoints later on rm -f ${DATA}/xtrabackup_binary ${DATA}/xtrabackup_galera_info ${DATA}/xtrabackup_logfile - ADDR=${WSREP_SST_OPT_ADDR} - if [ -z "${SST_PORT}" ] - then - SST_PORT=4444 - ADDR="$(echo ${WSREP_SST_OPT_ADDR} | awk -F ':' '{ print $1 }'):${SST_PORT}" - fi + ADDR="${WSREP_SST_OPT_HOST}:${WSREP_SST_OPT_PORT:-4444}" - wait_for_listen ${SST_PORT} ${ADDR} ${MODULE} & + wait_for_listen ${WSREP_SST_OPT_PORT:-4444} ${ADDR} ${MODULE} & trap sig_joiner_cleanup HUP PIPE INT TERM trap cleanup_joiner EXIT diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index b3c99cc4788..9c9f3919781 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -1,5 +1,5 @@ # Copyright (c) 2006, 2014, Oracle and/or its affiliates. -# Copyright (c) 2010, 2016, MariaDB Corporation +# Copyright (c) 2010, 2018, MariaDB Corporation # # 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 diff --git a/sql/contributors.h b/sql/contributors.h index 88a4a088acf..7369dcd141d 100644 --- a/sql/contributors.h +++ b/sql/contributors.h @@ -38,8 +38,9 @@ struct show_table_contributors_st { struct show_table_contributors_st show_table_contributors[]= { /* MariaDB foundation sponsors, in contribution, size , time order */ {"Booking.com", "https://www.booking.com", "Founding member, Platinum Sponsor of the MariaDB Foundation"}, - {"Alibaba Cloud", "https://intl.aliyun.com", "Platinum Sponsor of the MariaDB Foundation"}, + {"Alibaba Cloud", "https://www.alibabacloud.com/", "Platinum Sponsor of the MariaDB Foundation"}, {"Tencent Cloud", "https://cloud.tencent.com", "Platinum Sponsor of the MariaDB Foundation"}, + {"Microsoft", "https://microsoft.com/", "Platinum Sponsor of the MariaDB Foundation"}, {"MariaDB Corporation", "https://mariadb.com", "Founding member, Gold Sponsor of the MariaDB Foundation"}, {"Visma", "https://visma.com", "Gold Sponsor of the MariaDB Foundation"}, {"DBS", "https://dbs.com", "Gold Sponsor of the MariaDB Foundation"}, diff --git a/sql/field.cc b/sql/field.cc index f48638d81dc..5325597525b 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -2148,7 +2148,7 @@ uint Field::fill_cache_field(CACHE_FIELD *copy) { uint store_length; copy->str= ptr; - copy->length= pack_length(); + copy->length= pack_length_in_rec(); copy->field= this; if (flags & BLOB_FLAG) { @@ -9467,7 +9467,7 @@ int Field_bit::key_cmp(const uchar *str, uint length) str++; length--; } - return memcmp(ptr, str, length); + return memcmp(ptr, str, bytes_in_rec); } diff --git a/sql/field.h b/sql/field.h index 7fb746d7379..bc56ba4db7b 100644 --- a/sql/field.h +++ b/sql/field.h @@ -637,7 +637,7 @@ public: DBUG_ASSERT(size < UINT_MAX32); return thd_alloc(current_thd, (uint) size); } - static void operator delete(void *ptr_arg, size_t size) { TRASH(ptr_arg, size); } + static void operator delete(void *ptr_arg, size_t size) { TRASH_FREE(ptr_arg, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) { DBUG_ASSERT(0); } diff --git a/sql/field_conv.cc b/sql/field_conv.cc index 932188d56a8..a3c488a637d 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -607,7 +607,7 @@ void Copy_field::set(uchar *to,Field *from) { from_ptr=from->ptr; to_ptr=to; - from_length=from->pack_length(); + from_length=from->pack_length_in_rec(); if (from->maybe_null()) { from_null_ptr=from->null_ptr; @@ -655,9 +655,9 @@ void Copy_field::set(Field *to,Field *from,bool save) from_field=from; to_field=to; from_ptr=from->ptr; - from_length=from->pack_length(); + from_length=from->pack_length_in_rec(); to_ptr= to->ptr; - to_length=to_field->pack_length(); + to_length=to_field->pack_length_in_rec(); // set up null handling from_null_ptr=to_null_ptr=0; diff --git a/sql/handler.cc b/sql/handler.cc index 10c2b65bbc0..a7b92fcc769 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3459,9 +3459,11 @@ void print_keydup_error(TABLE *table, KEY *key, const char *msg, myf errflag) if (key == NULL) { - /* Key is unknown */ - str.copy("", 0, system_charset_info); - my_printf_error(ER_DUP_ENTRY, msg, errflag, str.c_ptr(), "*UNKNOWN*"); + /* + Key is unknown. Should only happen if storage engine reports wrong + duplicate key number. + */ + my_printf_error(ER_DUP_ENTRY, msg, errflag, "", "*UNKNOWN*"); } else { @@ -3561,11 +3563,9 @@ void handler::print_error(int error, myf errflag) if (table) { uint key_nr=get_dup_key(error); - if ((int) key_nr >= 0) + if ((int) key_nr >= 0 && key_nr < table->s->keys) { - print_keydup_error(table, - key_nr == MAX_KEY ? NULL : &table->key_info[key_nr], - errflag); + print_keydup_error(table, &table->key_info[key_nr], errflag); DBUG_VOID_RETURN; } } diff --git a/sql/item.cc b/sql/item.cc index d4da3f866d0..55c97e89ea5 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2010, 2017, MariaDB Corporation + Copyright (c) 2010, 2018, MariaDB Corporation 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 @@ -9153,7 +9153,7 @@ bool Item_ignore_value::send(Protocol *protocol, st_value *buffer) bool Item_insert_value::eq(const Item *item, bool binary_cmp) const { return item->type() == INSERT_VALUE_ITEM && - ((Item_default_value *)item)->arg->eq(arg, binary_cmp); + ((Item_insert_value *)item)->arg->eq(arg, binary_cmp); } @@ -10279,11 +10279,11 @@ const char *dbug_print_item(Item *item) ulonglong save_option_bits= thd->variables.option_bits; thd->variables.option_bits &= ~OPTION_QUOTE_SHOW_CREATE; - item->print(&str ,QT_EXPLAIN); + item->print(&str, QT_EXPLAIN); thd->variables.option_bits= save_option_bits; - if (str.c_ptr() == buf) + if (str.c_ptr_safe() == buf) return buf; else return "Couldn't fit into buffer"; diff --git a/sql/item.h b/sql/item.h index f4fff4a0418..94f05bc4a7f 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2,7 +2,7 @@ #define SQL_ITEM_INCLUDED /* Copyright (c) 2000, 2017, Oracle and/or its affiliates. - Copyright (c) 2009, 2017, MariaDB + Copyright (c) 2009, 2018, MariaDB Corporation 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 @@ -87,7 +87,11 @@ public: }; +#ifdef DBUG_OFF +static inline const char *dbug_print_item(Item *item) { return NULL; } +#else const char *dbug_print_item(Item *item); +#endif class Virtual_tmp_table; class sp_head; @@ -564,7 +568,7 @@ class Item: public Value_source, public: static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return alloc_root(mem_root, size); } - static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } + static void operator delete(void *ptr,size_t size) { TRASH_FREE(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) {} enum Type {FIELD_ITEM= 0, FUNC_ITEM, SUM_FUNC_ITEM, diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 313bd457313..5846ef094d9 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -1223,6 +1223,7 @@ bool Item_in_optimizer::is_top_level_item() void Item_in_optimizer::fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge) { + DBUG_ASSERT(fixed); /* This will re-calculate attributes of our Item_in_subselect: */ Item_bool_func::fix_after_pullout(new_parent, ref, merge); @@ -1246,6 +1247,33 @@ bool Item_in_optimizer::eval_not_null_tables(void *opt_arg) } +void Item_in_optimizer::print(String *str, enum_query_type query_type) +{ + restore_first_argument(); + Item_func::print(str, query_type); +} + + +/** + "Restore" first argument before fix_fields() call (after it is harmless). + + @Note: Main pointer to left part of IN/ALL/ANY subselect is subselect's + lest_expr (see Item_in_optimizer::fix_left) so changes made during + fix_fields will be rolled back there which can make + Item_in_optimizer::args[0] unusable on second execution before fix_left() + call. This call fix the pointer. +*/ + +void Item_in_optimizer::restore_first_argument() +{ + if (args[1]->type() == Item::SUBSELECT_ITEM && + ((Item_subselect *)args[1])->is_in_predicate()) + { + args[0]= ((Item_in_subselect *)args[1])->left_expr; + } +} + + bool Item_in_optimizer::fix_left(THD *thd) { DBUG_ENTER("Item_in_optimizer::fix_left"); @@ -1419,6 +1447,7 @@ bool Item_in_optimizer::invisible_mode() Item *Item_in_optimizer::expr_cache_insert_transformer(THD *thd, uchar *unused) { DBUG_ENTER("Item_in_optimizer::expr_cache_insert_transformer"); + DBUG_ASSERT(fixed); if (invisible_mode()) DBUG_RETURN(this); @@ -1443,6 +1472,7 @@ Item *Item_in_optimizer::expr_cache_insert_transformer(THD *thd, uchar *unused) void Item_in_optimizer::get_cache_parameters(List<Item> ¶meters) { + DBUG_ASSERT(fixed); /* Add left expression to the list of the parameters of the subquery */ if (!invisible_mode()) { @@ -1680,6 +1710,7 @@ Item *Item_in_optimizer::transform(THD *thd, Item_transformer transformer, { Item *new_item; + DBUG_ASSERT(fixed); DBUG_ASSERT(!thd->stmt_arena->is_stmt_prepare()); DBUG_ASSERT(arg_count == 2); @@ -1731,6 +1762,7 @@ Item *Item_in_optimizer::transform(THD *thd, Item_transformer transformer, bool Item_in_optimizer::is_expensive_processor(void *arg) { + DBUG_ASSERT(fixed); return args[0]->is_expensive_processor(arg) || args[1]->is_expensive_processor(arg); } @@ -1738,6 +1770,7 @@ bool Item_in_optimizer::is_expensive_processor(void *arg) bool Item_in_optimizer::is_expensive() { + DBUG_ASSERT(fixed); return args[0]->is_expensive() || args[1]->is_expensive(); } @@ -2680,7 +2713,9 @@ void Item_func_nullif::print(String *str, enum_query_type query_type) Therefore, after equal field propagation args[0] and args[2] can point to different items. */ - if ((query_type & QT_ITEM_ORIGINAL_FUNC_NULLIF) || args[0] == args[2]) + if ((query_type & QT_ITEM_ORIGINAL_FUNC_NULLIF) || + (arg_count == 2) || + (args[0] == args[2])) { /* If QT_ITEM_ORIGINAL_FUNC_NULLIF is requested, @@ -2698,10 +2733,14 @@ void Item_func_nullif::print(String *str, enum_query_type query_type) - one "a" for comparison - another "a" for the returned value! */ - DBUG_ASSERT(args[0] == args[2] || current_thd->lex->context_analysis_only); + DBUG_ASSERT(arg_count == 2 || + args[0] == args[2] || current_thd->lex->context_analysis_only); str->append(func_name()); str->append('('); - args[2]->print(str, query_type); + if (arg_count == 2) + args[0]->print(str, query_type); + else + args[2]->print(str, query_type); str->append(','); args[1]->print(str, query_type); str->append(')'); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index b4a833d2290..d4908ddf48d 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -378,6 +378,8 @@ public: void fix_after_pullout(st_select_lex *new_parent, Item **ref, bool merge); bool invisible_mode(); void reset_cache() { cache= NULL; } + virtual void print(String *str, enum_query_type query_type); + void restore_first_argument(); Item *get_copy(THD *thd, MEM_ROOT *mem_root) { return get_item_copy<Item_in_optimizer>(thd, mem_root, this); } }; @@ -2478,9 +2480,9 @@ public: bool arg_is_datetime_notnull_field() { Item **args= arguments(); - if (args[0]->type() == Item::FIELD_ITEM) + if (args[0]->real_item()->type() == Item::FIELD_ITEM) { - Field *field=((Item_field*) args[0])->field; + Field *field=((Item_field*) args[0]->real_item())->field; if (((field->type() == MYSQL_TYPE_DATE) || (field->type() == MYSQL_TYPE_DATETIME)) && diff --git a/sql/item_func.cc b/sql/item_func.cc index 7368aebcadf..cced6d70824 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -54,6 +54,7 @@ #include "set_var.h" #include "debug_sync.h" #include "sql_base.h" +#include "sql_cte.h" #ifdef NO_EMBEDDED_ACCESS_CHECKS #define sp_restore_security_context(A,B) while (0) {} @@ -703,6 +704,7 @@ my_decimal *Item_real_func::val_decimal(my_decimal *decimal_value) } +#ifdef HAVE_DLOPEN void Item_udf_func::fix_num_length_and_dec() { uint fl_length= 0; @@ -719,6 +721,7 @@ void Item_udf_func::fix_num_length_and_dec() max_length= float_length(NOT_FIXED_DEC); } } +#endif void Item_func::signal_divide_by_null() @@ -4511,10 +4514,13 @@ bool Item_func_set_user_var::fix_fields(THD *thd, Item **ref) TABLE_LIST *derived; for (derived= unit->derived; derived; - derived= derived->select_lex->master_unit()->derived) + derived= unit->derived) { derived->set_materialized_derived(); derived->prohibit_cond_pushdown= true; + if (unit->with_element && unit->with_element->is_recursive) + break; + unit= derived->select_lex->master_unit(); } } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index b39fcb78fe9..64fc84a49e8 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2017, Oracle and/or its affiliates. - Copyright (c) 2009, 2017, MariaDB + Copyright (c) 2009, 2018, MariaDB Corporation 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 @@ -202,9 +202,9 @@ String *Item_func_sha2::val_str_ascii(String *str) const char *input_ptr; size_t input_len; + input_string= args[0]->val_str(str); str->set_charset(&my_charset_bin); - input_string= args[0]->val_str(str); if (input_string == NULL) { null_value= TRUE; @@ -545,99 +545,106 @@ String *Item_func_decode_histogram::val_str(String *str) /////////////////////////////////////////////////////////////////////////////// +/* + Realloc the result buffer. + NOTE: We should be prudent in the initial allocation unit -- the + size of the arguments is a function of data distribution, which + can be any. Instead of overcommitting at the first row, we grow + the allocated amount by the factor of 2. This ensures that no + more than 25% of memory will be overcommitted on average. + + @param IN/OUT str - the result string + @param IN length - new total space required in "str" + @retval false - on success + @retval true - on error +*/ + +bool Item_func_concat::realloc_result(String *str, uint length) const +{ + if (str->alloced_length() >= length) + return false; // Alloced space is big enough, nothing to do. + + if (str->alloced_length() == 0) + return str->alloc(length); + + /* + Item_func_concat::val_str() makes sure the result length does not grow + higher than max_allowed_packet. So "length" is limited to 1G here. + We can't say anything about the current value of str->alloced_length(), + as str was initially set by args[0]->val_str(str). + So multiplication by 2 can overflow, if args[0] for some reasons + did not limit the result to max_alloced_packet. But it's not harmful, + "str" will be realloced exactly to "length" bytes in case of overflow. + */ + uint new_length= MY_MAX(str->alloced_length() * 2, length); + return str->realloc(new_length); +} + + /** Concatenate args with the following premises: If only one arg (which is ok), return value of arg; - Don't reallocate val_str() if not absolute necessary. */ String *Item_func_concat::val_str(String *str) { DBUG_ASSERT(fixed == 1); THD *thd= current_thd; - String *res,*use_as_buff; - uint i; - bool is_const= 0; + String *res; null_value=0; - if (!(res= arg_val_str(0, str, &is_const))) + if (!(res= args[0]->val_str(str))) goto null; - use_as_buff= &tmp_value; - for (i=1 ; i < arg_count ; i++) + + if (res != str) + str->copy(res->ptr(), res->length(), res->charset()); + + for (uint i= 1 ; i < arg_count ; i++) { - if (res->length() == 0) - { - /* - CONCAT accumulates its result in the result of its the first - non-empty argument. Because of this we need is_const to be - evaluated only for it. - */ - if (!(res= arg_val_str(i, str, &is_const))) - goto null; - } - else - { - const String *res2; - if (!(res2=args[i]->val_str(use_as_buff))) - goto null; - if (res2->length() == 0) - continue; - if (!(res= append_value(thd, res, is_const, str, &use_as_buff, res2))) - goto null; - is_const= 0; - } + if (!(res= args[i]->val_str(&tmp_value)) || + append_value(thd, str, res)) + goto null; } - res->set_charset(collation.collation); - return res; + + str->set_charset(collation.collation); + return str; null: - null_value=1; + null_value= true; return 0; } String *Item_func_concat_operator_oracle::val_str(String *str) { - THD *thd= current_thd; DBUG_ASSERT(fixed == 1); - String *res, *use_as_buff; + THD *thd= current_thd; + String *res; uint i; - bool is_const= false; - null_value= 0; + null_value=0; // Search first non null argument for (i= 0; i < arg_count; i++) { - if ((res= arg_val_str(i, str, &is_const))) + if ((res= args[i]->val_str(str))) break; } if (i == arg_count) goto null; - use_as_buff= &tmp_value; + if (res != str) + str->copy(res->ptr(), res->length(), res->charset()); for (i++ ; i < arg_count ; i++) { - if (res->length() == 0) - { - // See comments in Item_func_concat::val_str() - String *tmp; - if (!(tmp= arg_val_str(i, str, &is_const))) - continue; - res= tmp; - } - else - { - const String *res2; - if (!(res2= args[i]->val_str(use_as_buff)) || res2->length() == 0) - continue; - if (!(res= append_value(thd, res, is_const, str, &use_as_buff, res2))) - goto null; - is_const= 0; - } + if (!(res= args[i]->val_str(&tmp_value)) || res->length() == 0) + continue; + if (append_value(thd, str, res)) + goto null; } - res->set_charset(collation.collation); - return res; + + str->set_charset(collation.collation); + return str; null: null_value= true; @@ -645,115 +652,21 @@ null: } -String *Item_func_concat::append_value(THD *thd, - String *res, - bool res_is_const, - String *str, - String **use_as_buff, - const String *res2) +bool Item_func_concat::append_value(THD *thd, String *res, const String *app) { - DBUG_ASSERT(res2->length() > 0); - - if ((ulong) res->length() + (ulong) res2->length() > + uint concat_len; + if ((concat_len= res->length() + app->length()) > thd->variables.max_allowed_packet) { push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, ER_WARN_ALLOWED_PACKET_OVERFLOWED, - ER_THD(thd, ER_WARN_ALLOWED_PACKET_OVERFLOWED), - func_name(), + ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED), func_name(), thd->variables.max_allowed_packet); - return NULL; + return true; } - - uint32 concat_len= res->length() + res2->length(); - - if (!res_is_const && res->alloced_length() >= concat_len) - { // Use old buffer - return res->append(*res2) ? NULL : res; - } - - if (str->alloced_length() >= concat_len) - { - if (str->ptr() == res2->ptr()) - { - if (str->replace(0, 0, *res)) - return NULL; - } - else - { - if (str->copy(*res) || str->append(*res2)) - return NULL; - } - *use_as_buff= &tmp_value; - return str; - } - - if (res == &tmp_value) - { - if (res->append(*res2)) // Must be a blob - return NULL; - return res; - } - - if (res2 == &tmp_value) - { // This can happend only 1 time - if (tmp_value.replace(0, 0, *res)) - return NULL; - *use_as_buff= str; // Put next arg here - return &tmp_value; - } - - if (tmp_value.is_alloced() && res2->ptr() >= tmp_value.ptr() && - res2->ptr() <= tmp_value.ptr() + tmp_value.alloced_length()) - { - /* - This happens really seldom: - In this case res2 is sub string of tmp_value. We will - now work in place in tmp_value to set it to res | res2 - */ - /* Chop the last characters in tmp_value that isn't in res2 */ - tmp_value.length((uint32) (res2->ptr() - tmp_value.ptr()) + - res2->length()); - /* Place res2 at start of tmp_value, remove chars before res2 */ - if (tmp_value.replace(0,(uint32) (res2->ptr() - tmp_value.ptr()), - *res)) - return NULL; - *use_as_buff= str; // Put next arg here - return &tmp_value; - } - - /* - Two big const strings - NOTE: We should be prudent in the initial allocation unit -- the - size of the arguments is a function of data distribution, which - can be any. Instead of overcommitting at the first row, we grow - the allocated amount by the factor of 2. This ensures that no - more than 25% of memory will be overcommitted on average. - */ - - if (tmp_value.alloced_length() < concat_len) - { - if (tmp_value.alloced_length() == 0) - { - if (tmp_value.alloc(concat_len)) - return NULL; - } - else - { - uint32 new_len= tmp_value.alloced_length() > INT_MAX32 ? - UINT_MAX32 - 1 : - tmp_value.alloced_length() * 2; - set_if_bigger(new_len, concat_len); - if (tmp_value.realloc(new_len)) - return NULL; - } - } - - if (tmp_value.copy(*res) || tmp_value.append(*res2)) - return NULL; - - *use_as_buff= str; - return &tmp_value; + DBUG_ASSERT(!res->uses_buffer_owned_by(app)); + DBUG_ASSERT(!app->uses_buffer_owned_by(res)); + return realloc_result(res, concat_len) || res->append(*app); } diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 49f82f7028c..2b7cc1a3aa1 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -244,37 +244,14 @@ class Item_func_concat :public Item_str_func protected: String tmp_value; /* - Get the i-th argument val_str() and its const_item() - @param i[IN] - The argument number - @param str[IN] - The buffer for val_str() - @param is_const[IN/OUT] - If args[i]->val_str() returned a non-null value, - then args[i]->const_item() is returned here. - Otherwise, the value of is_const is not touched. - @retval - the result of val_str(). - */ - String *arg_val_str(uint i, String *str, bool *is_const) - { - String *res= args[i]->val_str(str); - if (res) - *is_const= args[i]->const_item(); - return res; - } - /* Append a non-NULL value to the result. @param [IN] thd - The current thread. @param [IN/OUT] res - The current val_str() return value. - @param [IN] res_is_const - If "false", then OK to append to "res" - @param [IN/OUT] str - The val_str() argument. - @param [IN] res2 - The value to be appended. - @param [IN/OUT] use_as_buff - Which buffer to use for the next argument: - args[next_arg]->val_str(use_as_buff) + @param [IN] app - The value to be appended. + @retval - false on success, true on error */ - String *append_value(THD *thd, - String *res, - bool res_is_const, - String *str, - String **use_as_buff, - const String *res2); + bool append_value(THD *thd, String *res, const String *app); + bool realloc_result(String *str, uint length) const; public: Item_func_concat(THD *thd, List<Item> &list): Item_str_func(thd, list) {} Item_func_concat(THD *thd, Item *a, Item *b): Item_str_func(thd, a, b) {} diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 6d00dcf650e..92691907e7c 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -2125,7 +2125,10 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join, } else { - Item *item= (Item*) select_lex->item_list.head()->real_item(); + Item *item= (Item*) select_lex->item_list.head(); + if (item->type() != REF_ITEM || + ((Item_ref*)item)->ref_type() != Item_ref::VIEW_REF) + item= item->real_item(); if (select_lex->table_list.elements) { @@ -5494,7 +5497,7 @@ int subselect_hash_sj_engine::exec() if (has_covering_null_row) { - DBUG_ASSERT(count_partial_match_columns = field_count); + DBUG_ASSERT(count_partial_match_columns == field_count); count_pm_keys= 0; } else if (has_covering_null_columns) diff --git a/sql/item_windowfunc.cc b/sql/item_windowfunc.cc index f993276dab3..45688b87730 100644 --- a/sql/item_windowfunc.cc +++ b/sql/item_windowfunc.cc @@ -440,5 +440,10 @@ void Item_window_func::print(String *str, enum_query_type query_type) { window_func()->print(str, query_type); str->append(" over "); +#ifndef DBUG_OFF + if (!window_spec) // one can call dbug_print_item() anytime in gdb + str->append(window_name); + else +#endif window_spec->print(str, query_type); } diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index a69d48e8328..af32bf9a46d 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -2734,7 +2734,7 @@ void Item_xml_str_func::fix_length_and_dec() bool Item_xml_str_func::fix_fields(THD *thd, Item **ref) { - String *xp, tmp; + String *xp; MY_XPATH xpath; int rc; @@ -2762,7 +2762,13 @@ bool Item_xml_str_func::fix_fields(THD *thd, Item **ref) return true; } - if (!(xp= args[1]->val_str(&tmp))) + /* + Get the XPath query text from args[1] and cache it in m_xpath_query. + Its fragments will be referenced by items created during my_xpath_parse(), + e.g. by Item_nodeset_func_axisbyname::node_name. + */ + if (!(xp= args[1]->val_str(&m_xpath_query)) || + (xp != &m_xpath_query && m_xpath_query.copy(*xp))) return false; // Will return NULL my_xpath_init(&xpath); xpath.thd= thd; diff --git a/sql/item_xmlfunc.h b/sql/item_xmlfunc.h index 3c071b897e2..d281e076ec8 100644 --- a/sql/item_xmlfunc.h +++ b/sql/item_xmlfunc.h @@ -62,6 +62,7 @@ protected: return parse(res, cache); } }; + String m_xpath_query; // XPath query text Item *nodeset_func; XML xml; bool get_xml(XML *xml_arg, bool cache= false) diff --git a/sql/key.cc b/sql/key.cc index 14d29e8b125..6369faff9d0 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -63,7 +63,8 @@ int find_ref_key(KEY *key, uint key_count, uchar *record, Field *field, i < (int) key_count ; i++, key_info++) { - if (key_info->key_part[0].offset == fieldpos) + if (key_info->key_part[0].offset == fieldpos && + key_info->key_part[0].field->type() != MYSQL_TYPE_BIT) { /* Found key. Calc keylength */ *key_length= *keypart= 0; return i; /* Use this key */ @@ -82,7 +83,8 @@ int find_ref_key(KEY *key, uint key_count, uchar *record, Field *field, j < key_info->user_defined_key_parts ; j++, key_part++) { - if (key_part->offset == fieldpos) + if (key_part->offset == fieldpos && + key_part->field->type() != MYSQL_TYPE_BIT) { *keypart= j; return i; /* Use this key */ diff --git a/sql/log_event.cc b/sql/log_event.cc index c559e8b5b4d..2c75045c94d 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -5324,8 +5324,13 @@ bool test_if_equal_repl_errors(int expected_error, int actual_error) return 1; switch (expected_error) { case ER_DUP_ENTRY: + case ER_DUP_ENTRY_WITH_KEY_NAME: + case ER_DUP_KEY: case ER_AUTOINC_READ_FAILED: - return (actual_error == ER_AUTOINC_READ_FAILED || + return (actual_error == ER_DUP_ENTRY || + actual_error == ER_DUP_ENTRY_WITH_KEY_NAME || + actual_error == ER_DUP_KEY || + actual_error == ER_AUTOINC_READ_FAILED || actual_error == HA_ERR_AUTOINC_ERANGE); case ER_UNKNOWN_TABLE: return actual_error == ER_IT_IS_A_VIEW; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 831b7b4be5d..c5804c7d315 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -553,7 +553,7 @@ ulong max_prepared_stmt_count; statements. */ ulong prepared_stmt_count=0; -my_thread_id global_thread_id= 1; +my_thread_id global_thread_id= 0; ulong current_pid; ulong slow_launch_threads = 0; uint sync_binlog_period= 0, sync_relaylog_period= 0, @@ -760,6 +760,9 @@ mysql_mutex_t LOCK_stats, LOCK_global_user_client_stats, /* This protects against changes in master_info_index */ mysql_mutex_t LOCK_active_mi; +/* This protects connection id.*/ +mysql_mutex_t LOCK_thread_id; + /** The below lock protects access to two global server variables: max_prepared_stmt_count and prepared_stmt_count. These variables @@ -927,6 +930,7 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list, key_LOCK_thread_count, key_LOCK_thread_cache, key_PARTITION_LOCK_auto_inc; PSI_mutex_key key_RELAYLOG_LOCK_index; +PSI_mutex_key key_LOCK_thread_id; PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state, key_LOCK_rpl_thread, key_LOCK_rpl_thread_pool, key_LOCK_parallel_entry; @@ -964,6 +968,7 @@ static PSI_mutex_info all_server_mutexes[]= { &key_hash_filo_lock, "hash_filo::lock", 0}, { &key_LOCK_active_mi, "LOCK_active_mi", PSI_FLAG_GLOBAL}, { &key_LOCK_connection_count, "LOCK_connection_count", PSI_FLAG_GLOBAL}, + { &key_LOCK_thread_id, "LOCK_thread_id", PSI_FLAG_GLOBAL}, { &key_LOCK_crypt, "LOCK_crypt", PSI_FLAG_GLOBAL}, { &key_LOCK_delayed_create, "LOCK_delayed_create", PSI_FLAG_GLOBAL}, { &key_LOCK_delayed_insert, "LOCK_delayed_insert", PSI_FLAG_GLOBAL}, @@ -2045,8 +2050,8 @@ pthread_handler_t kill_server_thread(void *arg __attribute__((unused))) extern "C" sig_handler print_signal_warning(int sig) { if (global_system_variables.log_warnings) - sql_print_warning("Got signal %d from thread %ld", sig, - (ulong) my_thread_id()); + sql_print_warning("Got signal %d from thread %u", sig, + (uint)my_thread_id()); #ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY my_sigset(sig,print_signal_warning); /* int. thread system calls */ #endif @@ -2333,6 +2338,7 @@ static void clean_up_mutexes() mysql_mutex_destroy(&LOCK_crypt); mysql_mutex_destroy(&LOCK_user_conn); mysql_mutex_destroy(&LOCK_connection_count); + mysql_mutex_destroy(&LOCK_thread_id); mysql_mutex_destroy(&LOCK_stats); mysql_mutex_destroy(&LOCK_global_user_client_stats); mysql_mutex_destroy(&LOCK_global_table_stats); @@ -4208,7 +4214,7 @@ static int init_common_variables() /* TODO: remove this when my_time_t is 64 bit compatible */ if (!IS_TIME_T_VALID_FOR_TIMESTAMP(server_start_time)) { - sql_print_error("This MySQL server doesn't support dates later then 2038"); + sql_print_error("This MySQL server doesn't support dates later than 2038"); exit(1); } @@ -4700,6 +4706,8 @@ static int init_thread_environment() &LOCK_short_uuid_generator, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_connection_count, &LOCK_connection_count, MY_MUTEX_INIT_FAST); + mysql_mutex_init(key_LOCK_thread_id, + &LOCK_thread_id, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_stats, &LOCK_stats, MY_MUTEX_INIT_FAST); mysql_mutex_init(key_LOCK_global_user_client_stats, &LOCK_global_user_client_stats, MY_MUTEX_INIT_FAST); @@ -8768,7 +8776,7 @@ static int mysql_init_variables(void) denied_connections= 0; executed_events= 0; global_query_id= 1; - global_thread_id= 1; + global_thread_id= 0; strnmov(server_version, MYSQL_SERVER_VERSION, sizeof(server_version)-1); threads.empty(); thread_cache.empty(); @@ -10442,3 +10450,96 @@ void init_server_psi_keys(void) } #endif /* HAVE_PSI_INTERFACE */ + + +/* + Connection ID allocation. + + We need to maintain thread_ids in the 32bit range, + because this is how it is passed to the client in the protocol. + + The idea is to maintain a id range, initially set to + (0,UINT32_MAX). Whenever new id is needed, we increment the + lower limit and return its new value. + + On "overflow", if id can not be generated anymore(i.e lower == upper -1), + we recalculate the range boundaries. + To do that, we first collect thread ids that are in use, by traversing + THD list, and find largest region within (0,UINT32_MAX), that is still free. + +*/ + +static my_thread_id thread_id_max= UINT_MAX32; + +#include <vector> +#include <algorithm> + +/* + Find largest unused thread_id range. + + i.e for every number N within the returned range, + there is no existing connection with thread_id equal to N. + + The range is exclusive, lower bound is always >=0 and + upper bound <=MAX_UINT32. + + @param[out] low - lower bound for the range + @param[out] high - upper bound for the range +*/ +static void recalculate_thread_id_range(my_thread_id *low, my_thread_id *high) +{ + std::vector<my_thread_id> ids; + + // Add sentinels + ids.push_back(0); + ids.push_back(UINT_MAX32); + + mysql_mutex_lock(&LOCK_thread_count); + + I_List_iterator<THD> it(threads); + THD *thd; + while ((thd=it++)) + ids.push_back(thd->thread_id); + + mysql_mutex_unlock(&LOCK_thread_count); + + std::sort(ids.begin(), ids.end()); + my_thread_id max_gap= 0; + for (size_t i= 0; i < ids.size() - 1; i++) + { + my_thread_id gap= ids[i+1] - ids[i]; + if (gap > max_gap) + { + *low= ids[i]; + *high= ids[i+1]; + max_gap= gap; + } + } + + if (max_gap < 2) + { + /* Can't find free id. This is not really possible, + we'd need 2^32 connections for this to happen.*/ + sql_print_error("Cannot find free connection id."); + abort(); + } +} + + +my_thread_id next_thread_id(void) +{ + my_thread_id retval; + DBUG_EXECUTE_IF("thread_id_overflow", global_thread_id= thread_id_max-2;); + + mysql_mutex_lock(&LOCK_thread_id); + + if (unlikely(global_thread_id == thread_id_max - 1)) + { + recalculate_thread_id_range(&global_thread_id, &thread_id_max); + } + + retval= ++global_thread_id; + + mysql_mutex_unlock(&LOCK_thread_id); + return retval; +} diff --git a/sql/mysqld.h b/sql/mysqld.h index 57698dc5d9b..5c6ad695354 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -732,15 +732,7 @@ inline query_id_t get_query_id() } /* increment global_thread_id and return it. */ -inline __attribute__((warn_unused_result)) my_thread_id next_thread_id() -{ - return my_atomic_add64_explicit((int64*) &global_thread_id, 1, MY_MEMORY_ORDER_RELAXED); -} - -#if defined(MYSQL_DYNAMIC_PLUGIN) && defined(_WIN32) -extern "C" my_thread_id next_thread_id_noinline(); -#define next_thread_id() next_thread_id_noinline() -#endif +extern __attribute__((warn_unused_result)) my_thread_id next_thread_id(void); /* TODO: Replace this with an inline function. diff --git a/sql/net_serv.cc b/sql/net_serv.cc index d9d35c5ed3f..7b988fd369b 100644 --- a/sql/net_serv.cc +++ b/sql/net_serv.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2012, 2017, MariaDB Corporation + Copyright (c) 2012, 2018, MariaDB Corporation. 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 @@ -58,6 +58,7 @@ #ifdef EXTRA_DEBUG #define EXTRA_DEBUG_fprintf fprintf #define EXTRA_DEBUG_fflush fflush +#define EXTRA_DEBUG_ASSERT DBUG_ASSERT #else static void inline EXTRA_DEBUG_fprintf(...) {} #ifndef MYSQL_SERVER @@ -70,6 +71,9 @@ static int inline EXTRA_DEBUG_fflush(...) { return 0; } static void inline MYSQL_SERVER_my_error(...) {} #endif +#ifndef EXTRA_DEBUG_ASSERT +# define EXTRA_DEBUG_ASSERT(X) do {} while(0) +#endif /* The following handles the differences when this is linked between the @@ -1085,7 +1089,7 @@ packets_out_of_order: ("Packets out of order (Found: %d, expected %u)", (int) net->buff[net->where_b + 3], net->pkt_nr)); - DBUG_ASSERT(0); + EXTRA_DEBUG_ASSERT(0); /* We don't make noise server side, since the client is expected to break the protocol for e.g. --send LOAD DATA .. LOCAL where diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 9c5dbc1c470..e90dbb468f1 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2074,7 +2074,7 @@ public: /* Table read plans are allocated on MEM_ROOT and are never deleted */ static void *operator new(size_t size, MEM_ROOT *mem_root) { return (void*) alloc_root(mem_root, (uint) size); } - static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } + static void operator delete(void *ptr,size_t size) { TRASH_FREE(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) { /* Never called */ } virtual ~TABLE_READ_PLAN() {} /* Remove gcc warning */ diff --git a/sql/sp.cc b/sql/sp.cc index 12d303ed85a..daf0744c904 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -808,7 +808,6 @@ static sp_head *sp_compile(THD *thd, String *defstr, sql_mode_t sql_mode, else { sp= thd->lex->sphead; - sp->set_select_number(thd->select_number); } thd->pop_internal_handler(); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 6a4e274d00a..bb56c69aa41 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -521,7 +521,7 @@ sp_head::sp_head(const Sp_handler *sph) m_defstr(null_clex_str), m_sp_cache_version(0), m_creation_ctx(0), - unsafe_flags(0), m_select_number(1), + unsafe_flags(0), m_created(0), m_modified(0), m_recursion_level(0), @@ -670,7 +670,7 @@ sp_head::~sp_head() thd->lex->sphead= NULL; lex_end(thd->lex); delete thd->lex; - thd->lex= lex; + thd->lex= thd->stmt_lex= lex; } my_hash_free(&m_sptabs); @@ -965,12 +965,13 @@ sp_head::execute(THD *thd, bool merge_da_on_success) backup_arena; query_id_t old_query_id; TABLE *old_derived_tables; - LEX *old_lex; + LEX *old_lex, *old_stmt_lex; Item_change_list old_change_list; String old_packet; uint old_server_status; const uint status_backup_mask= SERVER_STATUS_CURSOR_EXISTS | SERVER_STATUS_LAST_ROW_SENT; + MEM_ROOT *user_var_events_alloc_saved= 0; Reprepare_observer *save_reprepare_observer= thd->m_reprepare_observer; Object_creation_ctx *UNINIT_VAR(saved_creation_ctx); Diagnostics_area *da= thd->get_stmt_da(); @@ -980,19 +981,6 @@ sp_head::execute(THD *thd, bool merge_da_on_success) if (check_stack_overrun(thd, 7 * STACK_MIN_SIZE, (uchar*)&old_packet)) DBUG_RETURN(TRUE); - /* - Normally the counter is not reset between parsing and first execution, - but it is possible in case of error to have parsing on one CALL and - first execution (where VIEW will be parsed and added). So we store the - counter after parsing and restore it before execution just to avoid - repeating SELECT numbers. - - Other problem is that it can be more SELECTs parsed in case of fixing - error causes previous interruption of the SP. So it is save not just - assign old value but add it. - */ - thd->select_number+= m_select_number; - /* init per-instruction memroot */ init_sql_alloc(&execute_mem_root, "per_instruction_memroot", MEM_ROOT_BLOCK_SIZE, 0, MYF(0)); @@ -1082,6 +1070,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success) do it in each instruction */ old_lex= thd->lex; + old_stmt_lex= thd->stmt_lex; /* We should also save Item tree change list to avoid rollback something too early in the calling query. @@ -1162,9 +1151,11 @@ sp_head::execute(THD *thd, bool merge_da_on_success) Will write this SP statement into binlog separately. TODO: consider changing the condition to "not inside event union". */ - MEM_ROOT *user_var_events_alloc_saved= thd->user_var_events_alloc; if (thd->locked_tables_mode <= LTM_LOCK_TABLES) + { + user_var_events_alloc_saved= thd->user_var_events_alloc; thd->user_var_events_alloc= thd->mem_root; + } sql_digest_state *parent_digest= thd->m_digest; thd->m_digest= NULL; @@ -1228,6 +1219,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success) DBUG_ASSERT(thd->Item_change_list::is_empty()); old_change_list.move_elements_to(thd); thd->lex= old_lex; + thd->stmt_lex= old_stmt_lex; thd->set_query_id(old_query_id); DBUG_ASSERT(!thd->derived_tables); thd->derived_tables= old_derived_tables; @@ -1333,16 +1325,6 @@ sp_head::execute(THD *thd, bool merge_da_on_success) m_recursion_level + 1)); m_first_instance->m_first_free_instance= this; - /* - This execution of the SP was aborted with an error (e.g. "Table not - found"). However it might still have consumed some numbers from the - thd->select_number counter. The next sp->exec() call must not use the - consumed numbers, so we remember the first free number (We know that - nobody will use it as this execution has stopped with an error). - */ - if (err_status) - set_select_number(thd->select_number); - DBUG_RETURN(err_status); } @@ -3009,7 +2991,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, We should not save old value since it is saved/restored in sp_head::execute() when we are entering/leaving routine. */ - thd->lex= m_lex; + thd->lex= thd->stmt_lex= m_lex; thd->set_query_id(next_query_id()); diff --git a/sql/sp_head.h b/sql/sp_head.h index 9f6d4cd95e5..af1381647f0 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -240,7 +240,6 @@ private: */ uint32 unsafe_flags; - uint m_select_number; public: inline Stored_program_creation_ctx *get_creation_ctx() { @@ -823,8 +822,6 @@ public: sp_pcontext *get_parse_context() { return m_pcont; } - void set_select_number(uint num) { m_select_number= num; } - bool check_execute_access(THD *thd) const; private: diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index b62e3ae74d2..f2124818687 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -5963,8 +5963,8 @@ static bool merge_role_db_privileges(ACL_ROLE *grantee, const char *dbname, (that should be merged) are sorted together. The grantee's ACL_DB element is not necessarily the first and may be not present at all. */ - ACL_DB **first= NULL, *UNINIT_VAR(merged); - ulong UNINIT_VAR(access), update_flags= 0; + ACL_DB **first= NULL, *merged= NULL; + ulong access= 0, update_flags= 0; for (ACL_DB **cur= dbs.front(); cur <= dbs.back(); cur++) { if (!first || (!dbname && strcmp(cur[0]->db, cur[-1]->db))) @@ -6169,8 +6169,8 @@ static bool merge_role_table_and_column_privileges(ACL_ROLE *grantee, } grants.sort(table_name_sort); - GRANT_TABLE **first= NULL, *UNINIT_VAR(merged), **cur; - ulong UNINIT_VAR(privs), UNINIT_VAR(cols), update_flags= 0; + GRANT_TABLE **first= NULL, *merged= NULL, **cur; + ulong privs= 0, cols= 0, update_flags= 0; for (cur= grants.front(); cur <= grants.back(); cur++) { if (!first || @@ -6293,8 +6293,8 @@ static bool merge_role_routine_grant_privileges(ACL_ROLE *grantee, } grants.sort(routine_name_sort); - GRANT_NAME **first= NULL, *UNINIT_VAR(merged); - ulong UNINIT_VAR(privs); + GRANT_NAME **first= NULL, *merged= NULL; + ulong privs= 0 ; for (GRANT_NAME **cur= grants.front(); cur <= grants.back(); cur++) { if (!first || diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index c1c053670af..dd3f2e8abf8 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -700,8 +700,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, if (lock_type == TL_WRITE && !table->table->s->tmp_table && table->mdl_request.type > MDL_SHARED_WRITE) { - if (wait_while_table_is_used(thd, table->table, - HA_EXTRA_PREPARE_FOR_RENAME)) + if (wait_while_table_is_used(thd, table->table, HA_EXTRA_NOT_USED)) goto err; DEBUG_SYNC(thd, "after_admin_flush"); /* Flush entries in the query cache involving this table. */ diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 87ef4e0c03d..87a026ee743 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -8481,7 +8481,14 @@ int init_ftfuncs(THD *thd, SELECT_LEX *select_lex, bool no_order) DBUG_PRINT("info",("Performing FULLTEXT search")); while ((ifm=li++)) - ifm->init_search(thd, no_order); + if (unlikely(!ifm->fixed)) + /* + it mean that clause where was FT function was removed, so we have + to remove the function from the list. + */ + li.remove(); + else + ifm->init_search(thd, no_order); } return 0; } diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index dc5b2295b20..b85fb6e5b40 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -1188,7 +1188,11 @@ void Query_cache::end_of_result(THD *thd) #endif if (try_lock(thd, Query_cache::WAIT)) + { + if (is_disabled()) + query_cache_tls->first_query_block= NULL; // do not try again with QC DBUG_VOID_RETURN; + } query_block= query_cache_tls->first_query_block; if (query_block) @@ -1565,6 +1569,8 @@ def_week_frmt: %lu, in_trans: %d, autocommit: %d", unlock(); + DEBUG_SYNC(thd, "wait_in_query_cache_store_query"); + // init_n_lock make query block locked BLOCK_UNLOCK_WR(query_block); } @@ -2570,6 +2576,7 @@ void Query_cache::init() */ if (global_system_variables.query_cache_type == 0) { + m_cache_status= DISABLE_REQUEST; free_cache(); m_cache_status= DISABLED; } @@ -2778,13 +2785,17 @@ void Query_cache::make_disabled() This function frees all resources allocated by the cache. You have to call init_cache() before using the cache again. This function - requires the structure_guard_mutex to be locked. + requires the cache to be locked (LOCKED_NO_WAIT, lock_and_suspend) or + disabling. */ void Query_cache::free_cache() { DBUG_ENTER("Query_cache::free_cache"); + DBUG_ASSERT(m_cache_lock_status == LOCKED_NO_WAIT || + m_cache_status == DISABLE_REQUEST); + /* Destroy locks */ Query_cache_block *block= queries_blocks; if (block) @@ -2792,6 +2803,13 @@ void Query_cache::free_cache() do { Query_cache_query *query= block->query(); + /* + There will not be new requests but some maybe not finished yet, + so wait for them by trying lock/unlock + */ + BLOCK_LOCK_WR(block); + BLOCK_UNLOCK_WR(block); + mysql_rwlock_destroy(&query->lock); block= block->next; } while (block != queries_blocks); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index c5c29e4efbc..1cd9cd19a7b 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -785,6 +785,12 @@ THD::THD(my_thread_id id, bool is_wsrep_applier) init_sql_alloc(&main_mem_root, "THD::main_mem_root", ALLOC_ROOT_MIN_BLOCK_SIZE, 0, MYF(MY_THREAD_SPECIFIC)); + /* + Allocation of user variables for binary logging is always done with main + mem root + */ + user_var_events_alloc= mem_root; + stmt_arena= this; thread_stack= 0; scheduler= thread_scheduler; // Will be fixed later @@ -2770,6 +2776,9 @@ Item_change_list::check_and_register_item_tree_change(Item **place, MEM_ROOT *runtime_memroot) { Item_change_record *change; + DBUG_ENTER("THD::check_and_register_item_tree_change"); + DBUG_PRINT("enter", ("Register: %p (%p) <- %p (%p)", + *place, place, *new_value, new_value)); I_List_iterator<Item_change_record> it(change_list); while ((change= it++)) { @@ -2779,6 +2788,7 @@ Item_change_list::check_and_register_item_tree_change(Item **place, if (change) nocheck_register_item_tree_change(place, change->old_value, runtime_memroot); + DBUG_VOID_RETURN; } @@ -2786,17 +2796,13 @@ void Item_change_list::rollback_item_tree_changes() { I_List_iterator<Item_change_record> it(change_list); Item_change_record *change; - DBUG_ENTER("rollback_item_tree_changes"); while ((change= it++)) { - DBUG_PRINT("info", ("revert %p -> %p", - change->old_value, (*change->place))); *change->place= change->old_value; } /* We can forget about changes memory: it's allocated in runtime memroot */ change_list.empty(); - DBUG_VOID_RETURN; } @@ -3725,7 +3731,7 @@ void Statement::set_statement(Statement *stmt) { id= stmt->id; mark_used_columns= stmt->mark_used_columns; - lex= stmt->lex; + stmt_lex= lex= stmt->lex; query_string= stmt->query_string; } diff --git a/sql/sql_class.h b/sql/sql_class.h index cbd4b26f135..0edf61ce7d5 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1042,6 +1042,21 @@ public: LEX_CSTRING name; /* name for named prepared statements */ LEX *lex; // parse tree descriptor /* + LEX which represents current statement (conventional, SP or PS) + + For example during view parsing THD::lex will point to the views LEX and + THD::stmt_lex will point to LEX of the statement where the view will be + included + + Currently it is used to have always correct select numbering inside + statement (LEX::current_select_number) without storing and restoring a + global counter which was THD::select_number. + + TODO: make some unified statement representation (now SP has different) + to store such data like LEX::current_select_number. + */ + LEX *stmt_lex; + /* Points to the query associated with this statement. It's const, but we need to declare it char * because all table handlers are written in C and need to point to it. @@ -1198,6 +1213,29 @@ typedef struct st_xid_state { /* Error reported by the Resource Manager (RM) to the Transaction Manager. */ uint rm_error; XID_cache_element *xid_cache_element; + + /** + Check that XA transaction has an uncommitted work. Report an error + to the user in case when there is an uncommitted work for XA transaction. + + @return result of check + @retval false XA transaction is NOT in state IDLE, PREPARED + or ROLLBACK_ONLY. + @retval true XA transaction is in state IDLE or PREPARED + or ROLLBACK_ONLY. + */ + + bool check_has_uncommitted_xa() const + { + if (xa_state == XA_IDLE || + xa_state == XA_PREPARED || + xa_state == XA_ROLLBACK_ONLY) + { + my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]); + return true; + } + return false; + } } XID_STATE; void xid_cache_init(void); @@ -2872,7 +2910,6 @@ public: uint tmp_table, global_disable_checkpoint; uint server_status,open_options; enum enum_thread_type system_thread; - uint select_number; //number of select (used for EXPLAIN) /* Current or next transaction isolation level. When a connection is established, the value is taken from @@ -3655,10 +3692,14 @@ public: void change_item_tree(Item **place, Item *new_value) { + DBUG_ENTER("THD::change_item_tree"); + DBUG_PRINT("enter", ("Register: %p (%p) <- %p", + *place, place, new_value)); /* TODO: check for OOM condition here */ if (!stmt_arena->is_conventional()) nocheck_register_item_tree_change(place, *place, mem_root); *place= new_value; + DBUG_VOID_RETURN; } /** Make change in item tree after checking whether it needs registering @@ -4537,7 +4578,7 @@ public: void set_local_lex(sp_lex_local *sublex) { DBUG_ASSERT(lex->sphead); - lex= sublex; + lex= stmt_lex= sublex; /* Reset part of parser state which needs this. */ m_parser_state->m_yacc.reset_before_substatement(); } diff --git a/sql/sql_cte.cc b/sql/sql_cte.cc index d2298619f63..2fdd493b45d 100644 --- a/sql/sql_cte.cc +++ b/sql/sql_cte.cc @@ -223,7 +223,8 @@ With_element *With_clause::find_table_def(TABLE_LIST *table, with_elem= with_elem->next) { if (my_strcasecmp(system_charset_info, with_elem->query_name->str, - table->table_name) == 0) + table->table_name) == 0 && + !table->is_fqtn) { table->set_derived(); return with_elem; @@ -812,7 +813,7 @@ st_select_lex_unit *With_element::clone_parsed_spec(THD *thd, goto err; lex_start(thd); with_select= &lex->select_lex; - with_select->select_number= ++thd->select_number; + with_select->select_number= ++thd->stmt_lex->current_select_number; parse_status= parse_sql(thd, &parser_state, 0); if (parse_status) goto err; @@ -988,23 +989,20 @@ bool With_element::is_anchor(st_select_lex *sel) With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table) { - st_select_lex_unit *master_unit= NULL; With_element *found= NULL; - for (st_select_lex *sl= this; - sl; - sl= master_unit->outer_select()) + st_select_lex_unit *master_unit; + st_select_lex *outer_sl; + for (st_select_lex *sl= this; sl; sl= outer_sl) { - With_element *with_elem= sl->get_with_element(); /* If sl->master_unit() is the spec of a with element then the search for a definition was already done by With_element::check_dependencies_in_spec and it was unsuccesful. Yet for units cloned from the spec it has not been done yet. */ - With_clause *attached_with_clause=sl->get_with_clause(); - if (attached_with_clause && - (found= attached_with_clause->find_table_def(table, NULL))) - break; + master_unit= sl->master_unit(); + outer_sl= master_unit->outer_select(); + With_element *with_elem= sl->get_with_element(); if (with_elem) { With_clause *containing_with_clause= with_elem->get_owner(); @@ -1012,9 +1010,16 @@ With_element *st_select_lex::find_table_def_in_with_clauses(TABLE_LIST *table) NULL : with_elem; if ((found= containing_with_clause->find_table_def(table, barrier))) break; - sl= sl->master_unit()->outer_select(); + if (outer_sl && !outer_sl->get_with_element()) + break; + } + else + { + With_clause *attached_with_clause= sl->get_with_clause(); + if (attached_with_clause && + (found= attached_with_clause->find_table_def(table, NULL))) + break; } - master_unit= sl->master_unit(); /* Do not look for the table's definition beyond the scope of the view */ if (master_unit->is_view) break; diff --git a/sql/sql_cursor.cc b/sql/sql_cursor.cc index 40eb7046108..99d95c86b2f 100644 --- a/sql/sql_cursor.cc +++ b/sql/sql_cursor.cc @@ -215,7 +215,7 @@ void Server_side_cursor::operator delete(void *ptr, size_t size) MEM_ROOT own_root= *cursor->mem_root; DBUG_ENTER("Server_side_cursor::operator delete"); - TRASH(ptr, size); + TRASH_FREE(ptr, size); /* If this cursor has never been opened mem_root is empty. Otherwise mem_root points to the memory the cursor object was allocated in. diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index 3ed1417e7d0..22bdab685e3 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -369,7 +369,11 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) derived->get_unit())); if (derived->merged) + { + + DBUG_PRINT("info", ("Irreversibly merged: exit")); DBUG_RETURN(FALSE); + } if (dt_select->uncacheable & UNCACHEABLE_RAND) { @@ -384,7 +388,6 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) thd->save_prep_leaf_list= TRUE; arena= thd->activate_stmt_arena_if_needed(&backup); // For easier test - derived->merged= TRUE; if (!derived->merged_for_insert || (derived->is_multitable() && @@ -448,6 +451,7 @@ bool mysql_derived_merge(THD *thd, LEX *lex, TABLE_LIST *derived) if (parent_lex->join) parent_lex->join->table_count+= dt_select->join->table_count - 1; } + derived->merged= TRUE; if (derived->get_unit()->prepared) { Item *expr= derived->on_expr; @@ -745,6 +749,17 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived) } unit->derived= derived; + + /* + Above cascade call of prepare is important for PS protocol, but after it + is called we can check if we really need prepare for this derived + */ + if (derived->merged) + { + DBUG_PRINT("info", ("Irreversibly merged: exit")); + DBUG_RETURN(FALSE); + } + derived->fill_me= FALSE; if (!(derived->derived_result= new (thd->mem_root) select_unit(thd))) @@ -887,6 +902,11 @@ bool mysql_derived_optimize(THD *thd, LEX *lex, TABLE_LIST *derived) DBUG_PRINT("enter", ("Alias: '%s' Unit: %p", (derived->alias ? derived->alias : "<NULL>"), derived->get_unit())); + if (derived->merged) + { + DBUG_PRINT("info", ("Irreversibly merged: exit")); + DBUG_RETURN(FALSE); + } lex->current_select= first_select; diff --git a/sql/sql_explain.h b/sql/sql_explain.h index fb524263a8e..16781adf0f4 100644 --- a/sql/sql_explain.h +++ b/sql/sql_explain.h @@ -207,6 +207,9 @@ public: Explain_select(MEM_ROOT *root, bool is_analyze) : Explain_basic_join(root), +#ifndef DBUG_OFF + select_lex(NULL), +#endif linkage(UNSPECIFIED_TYPE), message(NULL), having(NULL), having_value(Item::COND_UNDEF), @@ -218,6 +221,9 @@ public: void add_linkage(Json_writer *writer); public: +#ifndef DBUG_OFF + SELECT_LEX *select_lex; +#endif const char *select_type; enum sub_select_type linkage; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 07b03baaf27..e5d2f88a857 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2016, Oracle and/or its affiliates. - Copyright (c) 2010, 2017, MariaDB + Copyright (c) 2010, 2018, MariaDB Corporation 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 diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index e6ef8a4be9f..3612cb6cc32 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -393,7 +393,7 @@ void JOIN_CACHE::create_flag_fields() TABLE *table= tab->table; /* Create a field for the null bitmap from table if needed */ - if (tab->used_null_fields || tab->used_uneven_bit_fields) + if (tab->used_null_fields || tab->used_uneven_bit_fields) length+= add_flag_field_to_join_cache(table->null_flags, table->s->null_bytes, ©); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index b8245ce0a09..b958a0b2e16 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2014, Oracle and/or its affiliates. - Copyright (c) 2009, 2017, MariaDB + Copyright (c) 2009, 2018, MariaDB Corporation 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 @@ -674,6 +674,8 @@ void lex_start(THD *thd) void LEX::start(THD *thd_arg) { DBUG_ENTER("LEX::start"); + DBUG_PRINT("info", ("This: %p thd_arg->lex: %p thd_arg->stmt_lex: %p", + this, thd_arg->lex, thd_arg->stmt_lex)); thd= unit.thd= thd_arg; @@ -682,6 +684,7 @@ void LEX::start(THD *thd_arg) context_stack.empty(); unit.init_query(); unit.init_select(); + current_select_number= 1; select_lex.linkage= UNSPECIFIED_TYPE; /* 'parent_lex' is used in init_query() so it must be before it. */ select_lex.parent_lex= this; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 9b50d28e58d..a0b109d590d 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2010, 2017, MariaDB Corporation. + Copyright (c) 2010, 2018, MariaDB Corporation 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 @@ -577,7 +577,7 @@ public: static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return (void*) alloc_root(mem_root, (uint) size); } - static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); } + static void operator delete(void *ptr,size_t size) { TRASH_FREE(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) {} // Ensures that at least all members used during cleanup() are initialized. @@ -852,7 +852,13 @@ public: Item *cond_pushed_into_having; /* condition pushed into the select's HAVING */ /* Saved values of the WHERE and HAVING clauses*/ Item::cond_result cond_value, having_value; - /* point on lex in which it was created, used in view subquery detection */ + /* + Point to the LEX in which it was created, used in view subquery detection. + + TODO: make also st_select_lex::parent_stmt_lex (see THD::stmt_lex) + and use st_select_lex::parent_lex & st_select_lex::parent_stmt_lex + instead of global (from THD) references where it is possible. + */ LEX *parent_lex; enum olap_type olap; /* FROM clause - points to the beginning of the TABLE_LIST::next_local list. */ @@ -2673,7 +2679,10 @@ struct LEX: public Query_tables_list DYNAMIC_ARRAY plugins; plugin_ref plugins_static_buffer[INITIAL_LEX_PLUGIN_LIST_SIZE]; - uint number_of_selects; // valid only for view + /** SELECT of CREATE VIEW statement */ + LEX_STRING create_view_select; + + uint current_select_number; // valid for statment LEX (not view) /** Start of 'ON table', in trigger statements. */ const char* raw_trg_on_table_name_begin; diff --git a/sql/sql_lifo_buffer.h b/sql/sql_lifo_buffer.h index 8fa13c66dd9..17024d15beb 100644 --- a/sql/sql_lifo_buffer.h +++ b/sql/sql_lifo_buffer.h @@ -84,7 +84,7 @@ public: start= start_arg; end= end_arg; if (end != start) - TRASH(start, end - start); + TRASH_ALLOC(start, end - start); reset(); } @@ -224,7 +224,7 @@ public: { DBUG_ASSERT(unused_end >= unused_start); DBUG_ASSERT(end == unused_start); - TRASH(unused_start, unused_end - unused_start); + TRASH_ALLOC(unused_start, unused_end - unused_start); end= unused_end; } /* Return pointer to start of the memory area that is occupied by the data */ diff --git a/sql/sql_list.h b/sql/sql_list.h index 111826495f7..4f76c495d3e 100644 --- a/sql/sql_list.h +++ b/sql/sql_list.h @@ -44,12 +44,12 @@ public: { return alloc_root(mem_root, size); } static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return alloc_root(mem_root, size); } - static void operator delete(void *ptr, size_t size) { TRASH(ptr, size); } + static void operator delete(void *ptr, size_t size) { TRASH_FREE(ptr, size); } static void operator delete(void *ptr, MEM_ROOT *mem_root) { /* never called */ } static void operator delete[](void *ptr, MEM_ROOT *mem_root) { /* never called */ } - static void operator delete[](void *ptr, size_t size) { TRASH(ptr, size); } + static void operator delete[](void *ptr, size_t size) { TRASH_FREE(ptr, size); } #ifdef HAVE_valgrind bool dummy_for_valgrind; inline Sql_alloc() :dummy_for_valgrind(0) {} diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c073adbceac..f8c09d82bf5 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -7476,7 +7476,12 @@ void THD::reset_for_next_command(bool do_clear_error) clear_error(1); thd->free_list= 0; - thd->select_number= 1; + /* + We also assign thd->stmt_lex in lex_start(), but during bootstrap this + code is executed first. + */ + thd->stmt_lex= &main_lex; thd->stmt_lex->current_select_number= 1; + DBUG_PRINT("info", ("Lex %p stmt_lex: %p", thd->lex, thd->stmt_lex)); /* Those two lines below are theoretically unneeded as THD::cleanup_after_query() should take care of this already. @@ -7526,10 +7531,9 @@ void THD::reset_for_next_command(bool do_clear_error) thd->thread_specific_used= FALSE; if (opt_bin_log) - { reset_dynamic(&thd->user_var_events); - thd->user_var_events_alloc= thd->mem_root; - } + DBUG_ASSERT(thd->user_var_events_alloc == &thd->main_mem_root); + thd->get_stmt_da()->reset_for_next_command(); thd->rand_used= 0; thd->m_sent_row_count= thd->m_examined_row_count= 0; @@ -7596,7 +7600,7 @@ mysql_new_select(LEX *lex, bool move_down, SELECT_LEX *select_lex) { if (!(select_lex= new (thd->mem_root) SELECT_LEX())) DBUG_RETURN(1); - select_lex->select_number= ++thd->select_number; + select_lex->select_number= ++thd->stmt_lex->current_select_number; select_lex->parent_lex= lex; /* Used in init_query. */ select_lex->init_query(); select_lex->init_select(); diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc index f951a81331b..173a7391e99 100644 --- a/sql/sql_partition.cc +++ b/sql/sql_partition.cc @@ -4431,8 +4431,14 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info, !thd->lex->part_info->num_columns) thd->lex->part_info->num_columns= 1; // to make correct clone - if ((thd->work_part_info= thd->lex->part_info) && - !(thd->work_part_info= thd->lex->part_info->get_clone(thd))) + /* + One of these is done in handle_if_exists_option(): + thd->work_part_info= thd->lex->part_info; + or + thd->work_part_info= NULL; + */ + if (thd->work_part_info && + !(thd->work_part_info= thd->work_part_info->get_clone(thd))) DBUG_RETURN(TRUE); /* ALTER_ADMIN_PARTITION is handled in mysql_admin_table */ diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 2b3ee37213a..0a72e3c3d5a 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -488,6 +488,11 @@ static st_plugin_dl *plugin_dl_insert_or_reuse(struct st_plugin_dl *plugin_dl) sizeof(struct st_plugin_dl)); DBUG_RETURN(tmp); } +#else +static struct st_plugin_dl *plugin_dl_find(const LEX_STRING *) +{ + return 0; +} #endif /* HAVE_DLOPEN */ diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 2fd0f9c0531..52200798cf3 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -167,20 +167,6 @@ public: uint param_count; uint last_errno; uint flags; - /* - The value of thd->select_number at the end of the PREPARE phase. - - The issue is: each statement execution opens VIEWs, which may cause - select_lex objects to be created, and select_number values to be assigned. - - On the other hand, PREPARE assigns select_number values for triggers and - subqueries. - - In order for select_number values from EXECUTE not to conflict with - select_number values from PREPARE, we keep the number and set it at each - execution. - */ - uint select_number_after_prepare; char last_error[MYSQL_ERRMSG_SIZE]; my_bool iterations; my_bool start_param; @@ -3796,9 +3782,9 @@ void Prepared_statement::cleanup_stmt() DBUG_ENTER("Prepared_statement::cleanup_stmt"); DBUG_PRINT("enter",("stmt: %p", this)); thd->restore_set_statement_var(); + thd->rollback_item_tree_changes(); cleanup_items(free_list); thd->cleanup_after_query(); - thd->rollback_item_tree_changes(); DBUG_VOID_RETURN; } @@ -3883,6 +3869,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) if (! (lex= new (mem_root) st_lex_local)) DBUG_RETURN(TRUE); + stmt_lex= lex; if (set_db(thd->db, thd->db_length)) DBUG_RETURN(TRUE); @@ -3988,8 +3975,6 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len) trans_rollback_implicit(thd); thd->mdl_context.release_transactional_locks(); } - - select_number_after_prepare= thd->select_number; /* Preserve CHANGE MASTER attributes */ lex_end_stage1(lex); @@ -4126,7 +4111,6 @@ Prepared_statement::execute_loop(String *expanded_query, */ DBUG_ASSERT(thd->free_list == NULL); - thd->select_number= select_number_after_prepare; /* Check if we got an error when sending long data */ if (state == Query_arena::STMT_ERROR) { @@ -4269,7 +4253,6 @@ Prepared_statement::execute_bulk_loop(String *expanded_query, #ifndef DBUG_OFF Item *free_list_state= thd->free_list; #endif - thd->select_number= select_number_after_prepare; thd->set_bulk_execution((void *)this); /* Check if we got an error when sending long data */ if (state == Query_arena::STMT_ERROR) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index f88db1048ad..6fd161f7160 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2016 Oracle and/or its affiliates. - Copyright (c) 2009, 2016 MariaDB + Copyright (c) 2009, 2018 MariaDB Corporation 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 @@ -283,6 +283,9 @@ JOIN_TAB *next_depth_first_tab(JOIN* join, JOIN_TAB* tab); static JOIN_TAB *next_breadth_first_tab(JOIN_TAB *first_top_tab, uint n_top_tabs_count, JOIN_TAB *tab); +static bool find_order_in_list(THD *, Ref_ptr_array, TABLE_LIST *, ORDER *, + List<Item> &, List<Item> &, bool, bool, bool); + static double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s, table_map rem_tables); void set_postjoin_aggr_write_func(JOIN_TAB *tab); @@ -334,7 +337,7 @@ bool dbug_user_var_equals_int(THD *thd, const char *name, int value) } return FALSE; } -#endif +#endif /** @@ -710,6 +713,9 @@ JOIN::prepare(TABLE_LIST *tables_init, join_list= &select_lex->top_join_list; union_part= unit_arg->is_unit_op(); + // simple check that we got usable conds + dbug_print_item(conds); + if (select_lex->handle_derived(thd->lex, DT_PREPARE)) DBUG_RETURN(1); @@ -825,9 +831,15 @@ JOIN::prepare(TABLE_LIST *tables_init, { nesting_map save_allow_sum_func= thd->lex->allow_sum_func; thd->lex->allow_sum_func|= (nesting_map)1 << select_lex->nest_level; - if (setup_order(thd, ref_ptrs, tables_list, fields_list, - all_fields, select_lex->order_list.first)) - DBUG_RETURN(-1); + thd->where= "order clause"; + for (ORDER *order= select_lex->order_list.first; order; order= order->next) + { + /* Don't add the order items to all fields. Just resolve them to ensure + the query is valid, we'll drop them immediately after. */ + if (find_order_in_list(thd, ref_ptrs, tables_list, order, + fields_list, all_fields, false, false, false)) + DBUG_RETURN(-1); + } thd->lex->allow_sum_func= save_allow_sum_func; select_lex->order_list.empty(); } @@ -3203,8 +3215,11 @@ bool JOIN::shrink_join_buffers(JOIN_TAB *jt, ulonglong curr_space, ulonglong needed_space) { + JOIN_TAB *tab; JOIN_CACHE *cache; - for (JOIN_TAB *tab= join_tab+const_tables; tab < jt; tab++) + for (tab= first_linear_tab(this, WITHOUT_BUSH_ROOTS, WITHOUT_CONST_TABLES); + tab != jt; + tab= next_linear_tab(this, tab, WITHOUT_BUSH_ROOTS)) { cache= tab->cache; if (cache) @@ -3341,6 +3356,17 @@ void JOIN::save_explain_data(Explain_query *output, bool can_overwrite, bool need_tmp_table, bool need_order, bool distinct) { + /* + If there is SELECT in this statemet with the same number it must be the + same SELECT + */ + DBUG_ASSERT(select_lex->select_number == UINT_MAX || + select_lex->select_number == INT_MAX || + !output || + !output->get_select(select_lex->select_number) || + output->get_select(select_lex->select_number)->select_lex == + select_lex); + if (select_lex->select_number != UINT_MAX && select_lex->select_number != INT_MAX /* this is not a UNION's "fake select */ && have_query_plan != JOIN::QEP_NOT_PRESENT_YET && @@ -10880,7 +10906,7 @@ void JOIN::drop_unused_derived_keys() tmp_tbl->use_index(tab->ref.key); if (tmp_tbl->s->keys) { - if (tab->ref.key >= 0) + if (tab->ref.key >= 0 && tab->ref.key < MAX_KEY) tab->ref.key= 0; else tmp_tbl->s->keys= 0; @@ -12704,8 +12730,8 @@ static void update_depend_map(JOIN *join) uint i; for (i=0 ; i < ref->key_parts ; i++,item++) depend_map|=(*item)->used_tables(); - ref->depend_map=depend_map & ~OUTER_REF_TABLE_BIT; depend_map&= ~OUTER_REF_TABLE_BIT; + ref->depend_map= depend_map; for (JOIN_TAB **tab=join->map2table; depend_map ; tab++,depend_map>>=1 ) @@ -13109,7 +13135,7 @@ public: } static void operator delete(void *ptr __attribute__((unused)), size_t size __attribute__((unused))) - { TRASH(ptr, size); } + { TRASH_FREE(ptr, size); } Item *and_level; Item_bool_func2 *cmp_func; @@ -16085,9 +16111,10 @@ COND * Item_func_isnull::remove_eq_conds(THD *thd, Item::cond_result *cond_value, bool top_level_arg) { - if (args[0]->type() == Item::FIELD_ITEM) + Item *real_item= args[0]->real_item(); + if (real_item->type() == Item::FIELD_ITEM) { - Field *field= ((Item_field*) args[0])->field; + Field *field= ((Item_field*) real_item)->field; if (((field->type() == MYSQL_TYPE_DATE) || (field->type() == MYSQL_TYPE_DATETIME)) && @@ -17313,7 +17340,7 @@ create_tmp_table(THD *thd, TMP_TABLE_PARAM *param, List<Item> &fields, field->set_notnull(); memcpy(field->ptr, orig_field->ptr_in_record(orig_field->table->s->default_values), - field->pack_length()); + field->pack_length_in_rec()); } } @@ -22603,7 +22630,10 @@ cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref) SELECT list) @param[in,out] all_fields All select, group and order by fields @param[in] is_group_field True if order is a GROUP field, false if - ORDER by field + ORDER by field + @param[in] add_to_all_fields If the item is to be added to all_fields and + ref_pointer_array, this flag can be set to + false to stop the automatic insertion. @param[in] from_window_spec If true then order is from a window spec @retval @@ -22613,9 +22643,11 @@ cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref) */ static bool -find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, +find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array, + TABLE_LIST *tables, ORDER *order, List<Item> &fields, List<Item> &all_fields, - bool is_group_field, bool from_window_spec) + bool is_group_field, bool add_to_all_fields, + bool from_window_spec) { Item *order_item= *order->item; /* The item from the GROUP/ORDER caluse. */ Item::Type order_item_type; @@ -22752,6 +22784,9 @@ find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables thd->is_error())) return TRUE; /* Wrong field. */ + if (!add_to_all_fields) + return FALSE; + uint el= all_fields.elements; /* Add new field to field list. */ all_fields.push_front(order_item, thd->mem_root); @@ -22780,7 +22815,7 @@ find_order_in_list(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables */ int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, - List<Item> &fields, List<Item> &all_fields, ORDER *order, + List<Item> &fields, List<Item> &all_fields, ORDER *order, bool from_window_spec) { enum_parsing_place context_analysis_place= @@ -22789,7 +22824,7 @@ int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, for (; order; order=order->next) { if (find_order_in_list(thd, ref_pointer_array, tables, order, fields, - all_fields, FALSE, from_window_spec)) + all_fields, false, true, from_window_spec)) return 1; if ((*order->item)->with_window_func && context_analysis_place != IN_ORDER_BY) @@ -22848,7 +22883,7 @@ setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, for (ord= order; ord; ord= ord->next) { if (find_order_in_list(thd, ref_pointer_array, tables, ord, fields, - all_fields, TRUE, from_window_spec)) + all_fields, true, true, from_window_spec)) return 1; (*ord->item)->marker= UNDEF_POS; /* Mark found */ if ((*ord->item)->with_sum_func && context_analysis_place == IN_GROUP_BY) @@ -23173,6 +23208,7 @@ get_sort_by_table(ORDER *a,ORDER *b, List<TABLE_LIST> &tables, if (!map || (map & (RAND_TABLE_BIT | OUTER_REF_TABLE_BIT))) DBUG_RETURN(0); + map&= ~const_tables; while ((table= ti++) && !(map & table->table->map)) ; if (map != table->table->map) DBUG_RETURN(0); // More than one table @@ -25155,6 +25191,11 @@ int JOIN::save_explain_data_intern(Explain_query *output, { explain= new (output->mem_root) Explain_select(output->mem_root, thd->lex->analyze_stmt); + if (!explain) + DBUG_RETURN(1); // EoM +#ifndef DBUG_OFF + explain->select_lex= select_lex; +#endif join->select_lex->set_explain_type(true); explain->select_id= join->select_lex->select_number; diff --git a/sql/sql_select.h b/sql/sql_select.h index 3f1fdac96cb..eb78f4216f9 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1976,7 +1976,7 @@ int report_error(TABLE *table, int error); int safe_index_read(JOIN_TAB *tab); int get_quick_record(SQL_SELECT *select); int setup_order(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, - List<Item> &fields, List <Item> &all_fields, ORDER *order, + List<Item> &fields, List <Item> &all_fields, ORDER *order, bool from_window_spec= false); int setup_group(THD *thd, Ref_ptr_array ref_pointer_array, TABLE_LIST *tables, List<Item> &fields, List<Item> &all_fields, ORDER *order, @@ -2057,7 +2057,7 @@ public: @param thd - Current thread. */ static void *operator new(size_t size, THD *thd) throw(); - static void operator delete(void *ptr, size_t size) { TRASH(ptr, size); } + static void operator delete(void *ptr, size_t size) {TRASH_FREE(ptr, size);} Virtual_tmp_table(THD *thd) { diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 919e2871b40..604b228b263 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2611,7 +2611,7 @@ public: { return alloc_root(mem_root, size); } static void operator delete(void *ptr __attribute__((unused)), size_t size __attribute__((unused))) - { TRASH(ptr, size); } + { TRASH_FREE(ptr, size); } my_thread_id thread_id; uint32 os_thread_id; diff --git a/sql/sql_string.h b/sql/sql_string.h index 3908cdff252..98c87f45d8f 100644 --- a/sql/sql_string.h +++ b/sql/sql_string.h @@ -185,7 +185,7 @@ public: { (void) ptr_arg; (void) size; - TRASH(ptr_arg, size); + TRASH_FREE(ptr_arg, size); } static void operator delete(void *, MEM_ROOT *) { /* never called */ } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 44d507412ec..41d8d8f4603 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1834,7 +1834,8 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags) #endif /* Write shadow frm file */ lpt->create_info->table_options= lpt->db_options; - LEX_CUSTRING frm= build_frm_image(lpt->thd, lpt->table_name, + LEX_CUSTRING frm= build_frm_image(lpt->thd, + lpt->table_name, lpt->create_info, lpt->alter_info->create_list, lpt->key_count, lpt->key_info_buffer, @@ -5980,6 +5981,7 @@ remove_key: #ifdef WITH_PARTITION_STORAGE_ENGINE partition_info *tab_part_info= table->part_info; + thd->work_part_info= thd->lex->part_info; if (tab_part_info) { /* ALTER TABLE ADD PARTITION IF NOT EXISTS */ @@ -6000,7 +6002,7 @@ remove_key: ER_THD(thd, ER_SAME_NAME_PARTITION), pe->partition_name); alter_info->flags&= ~Alter_info::ALTER_ADD_PARTITION; - thd->lex->part_info= NULL; + thd->work_part_info= NULL; break; } } @@ -9887,11 +9889,12 @@ copy_data_between_tables(THD *thd, TABLE *from, TABLE *to, if ((int) key_nr >= 0) { const char *err_msg= ER_THD(thd, ER_DUP_ENTRY_WITH_KEY_NAME); - if (key_nr == 0 && + if (key_nr == 0 && to->s->keys > 0 && (to->key_info[0].key_part[0].field->flags & AUTO_INCREMENT_FLAG)) err_msg= ER_THD(thd, ER_DUP_ENTRY_AUTOINCREMENT_CASE); - print_keydup_error(to, key_nr == MAX_KEY ? NULL : + print_keydup_error(to, + key_nr >= to->s->keys ? NULL : &to->key_info[key_nr], err_msg, MYF(0)); } diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index ebc5b28f598..a919994c90c 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1362,11 +1362,12 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, List_iterator_fast<LEX_CSTRING> it_connection_cl_name(trigger_list->connection_cl_names); List_iterator_fast<LEX_CSTRING> it_db_cl_name(trigger_list->db_cl_names); List_iterator_fast<ulonglong> it_create_times(trigger_list->create_times); - LEX *old_lex= thd->lex, lex; + LEX *old_lex= thd->lex, *old_stmt_lex= thd->stmt_lex; + LEX lex; sp_rcontext *save_spcont= thd->spcont; sql_mode_t save_sql_mode= thd->variables.sql_mode; - thd->lex= &lex; + thd->lex= thd->stmt_lex= &lex; save_db.str= thd->db; save_db.length= thd->db_length; @@ -1585,6 +1586,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, } thd->reset_db(save_db.str, save_db.length); thd->lex= old_lex; + thd->stmt_lex= old_stmt_lex; thd->spcont= save_spcont; thd->variables.sql_mode= save_sql_mode; @@ -1598,6 +1600,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, err_with_lex_cleanup: lex_end(&lex); thd->lex= old_lex; + thd->stmt_lex= old_stmt_lex; thd->spcont= save_spcont; thd->variables.sql_mode= save_sql_mode; thd->reset_db(save_db.str, save_db.length); diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 47286f1df14..909ef887928 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -1793,22 +1793,6 @@ void st_select_lex_unit::reinit_exec_mechanism() { prepared= optimized= optimized_2= executed= 0; optimize_started= 0; -#ifndef DBUG_OFF - if (is_unit_op()) - { - List_iterator_fast<Item> it(item_list); - Item *field; - while ((field= it++)) - { - /* - we can't cleanup here, because it broke link to temporary table field, - but have to drop fixed flag to allow next fix_field of this field - during re-executing - */ - field->fixed= 0; - } - } -#endif if (with_element && with_element->is_recursive) with_element->reset_recursive_for_exec(); } diff --git a/sql/sql_view.cc b/sql/sql_view.cc index c5a2555178d..0a13a630487 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1200,8 +1200,6 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, */ mysql_derived_reinit(thd, NULL, table); - thd->select_number+= table->view->number_of_selects; - DEBUG_SYNC(thd, "after_cached_view_opened"); DBUG_RETURN(0); } @@ -1357,7 +1355,7 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, lex_start(thd); view_select= &lex->select_lex; - view_select->select_number= ++thd->select_number; + view_select->select_number= ++thd->stmt_lex->current_select_number; sql_mode_t saved_mode= thd->variables.sql_mode; /* switch off modes which can prevent normal parsing of VIEW @@ -1392,9 +1390,6 @@ bool mysql_make_view(THD *thd, TABLE_SHARE *share, TABLE_LIST *table, parse_status= parse_sql(thd, & parser_state, table->view_creation_ctx); - lex->number_of_selects= - (thd->select_number - view_select->select_number) + 1; - /* Restore environment. */ if ((old_lex->sql_command == SQLCOM_SHOW_FIELDS) || diff --git a/sql/table.cc b/sql/table.cc index afd6b14079f..7502a13d5ce 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1601,9 +1601,10 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, rec_buff_length= ALIGN_SIZE(share->reclength + 1); share->rec_buff_length= rec_buff_length; - if (!(record= (uchar *) alloc_root(&share->mem_root, - rec_buff_length))) + if (!(record= (uchar *) alloc_root(&share->mem_root, rec_buff_length))) goto err; /* purecov: inspected */ + MEM_NOACCESS(record, rec_buff_length); + MEM_UNDEFINED(record, share->reclength); share->default_values= record; memcpy(record, frm_image + record_offset, share->reclength); @@ -3089,6 +3090,7 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, if (!(record= (uchar*) alloc_root(&outparam->mem_root, share->rec_buff_length * records))) goto err; /* purecov: inspected */ + MEM_NOACCESS(record, share->rec_buff_length * records); if (records == 0) { @@ -3103,6 +3105,8 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, else outparam->record[1]= outparam->record[0]; // Safety } + MEM_UNDEFINED(outparam->record[0], share->reclength); + MEM_UNDEFINED(outparam->record[1], share->reclength); if (!(field_ptr = (Field **) alloc_root(&outparam->mem_root, (uint) ((share->fields+1)* diff --git a/sql/threadpool_generic.cc b/sql/threadpool_generic.cc index f6fdd97c6df..400d072df3c 100644 --- a/sql/threadpool_generic.cc +++ b/sql/threadpool_generic.cc @@ -1698,10 +1698,9 @@ int TP_pool_generic::set_pool_size(uint size) if(!success) { sql_print_error("io_poll_create() failed, errno=%d\n", errno); - break; } } - mysql_mutex_unlock(&all_groups[i].mutex); + mysql_mutex_unlock(&group->mutex); if (!success) { group_count= i; diff --git a/sql/transaction.cc b/sql/transaction.cc index 78cd3047f82..a6db204c45b 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -611,12 +611,8 @@ bool trans_savepoint(THD *thd, LEX_CSTRING name) !opt_using_transactions) DBUG_RETURN(FALSE); - enum xa_states xa_state= thd->transaction.xid_state.xa_state; - if (xa_state != XA_NOTR && xa_state != XA_ACTIVE) - { - my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]); + if (thd->transaction.xid_state.check_has_uncommitted_xa()) DBUG_RETURN(TRUE); - } sv= find_savepoint(thd, name); @@ -691,12 +687,8 @@ bool trans_rollback_to_savepoint(THD *thd, LEX_CSTRING name) DBUG_RETURN(TRUE); } - enum xa_states xa_state= thd->transaction.xid_state.xa_state; - if (xa_state != XA_NOTR) - { - my_error(ER_XAER_RMFAIL, MYF(0), xa_state_names[xa_state]); + if (thd->transaction.xid_state.check_has_uncommitted_xa()) DBUG_RETURN(TRUE); - } /** Checking whether it is safe to release metadata locks acquired after diff --git a/sql/unireg.cc b/sql/unireg.cc index b49c3cfbb09..1342e4c2b66 100644 --- a/sql/unireg.cc +++ b/sql/unireg.cc @@ -1,6 +1,6 @@ /* Copyright (c) 2000, 2011, Oracle and/or its affiliates. - Copyright (c) 2009, 2013, Monty Program Ab. + Copyright (c) 2009, 2018, MariaDB Corporation 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 @@ -87,7 +87,7 @@ static uchar *extra2_write(uchar *pos, enum extra2_frm_value_type type, return extra2_write(pos, type, reinterpret_cast<LEX_CSTRING *>(str)); } -/** +/* Create a frm (table definition) file @param thd Thread handler @@ -175,7 +175,8 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, DBUG_PRINT("info", ("Options length: %u", options_len)); if (validate_comment_length(thd, &create_info->comment, TABLE_COMMENT_MAXLEN, - ER_TOO_LONG_TABLE_COMMENT, table)) + ER_TOO_LONG_TABLE_COMMENT, + table)) DBUG_RETURN(frm); /* If table comment is longer than TABLE_COMMENT_INLINE_MAXLEN bytes, @@ -280,6 +281,14 @@ LEX_CUSTRING build_frm_image(THD *thd, const char *table, DBUG_ASSERT(pos == frm_ptr + uint2korr(fileinfo+6)); key_info_length= pack_keys(pos, keys, key_info, data_offset); + if (key_info_length > UINT_MAX16) + { + my_printf_error(ER_CANT_CREATE_TABLE, + "Cannot create table %`s: index information is too long. " + "Decrease number of indexes or use shorter index names or shorter comments.", + MYF(0), table); + goto err; + } int2store(forminfo+2, frm.length - filepos); int4store(fileinfo+10, frm.length); diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 8626cb07196..ba611fed0c7 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -30,9 +30,10 @@ #include <cstdio> #include <cstdlib> -char wsrep_defaults_file[FN_REFLEN * 2 + 10 + - sizeof(WSREP_SST_OPT_CONF) + - sizeof(WSREP_SST_OPT_EXTRA_CONF)] = {0}; +static char wsrep_defaults_file[FN_REFLEN * 2 + 10 + 30 + + sizeof(WSREP_SST_OPT_CONF) + + sizeof(WSREP_SST_OPT_CONF_SUFFIX) + + sizeof(WSREP_SST_OPT_CONF_EXTRA)] = {0}; // container for real auth string static const char* sst_auth_real = NULL; @@ -69,7 +70,11 @@ static void make_wsrep_defaults_file() if (my_defaults_extra_file) ptr= strxnmov(ptr, end - ptr, - WSREP_SST_OPT_EXTRA_CONF, " '", my_defaults_extra_file, "' ", NULL); + WSREP_SST_OPT_CONF_EXTRA, " '", my_defaults_extra_file, "' ", NULL); + + if (my_defaults_group_suffix) + ptr= strxnmov(ptr, end - ptr, + WSREP_SST_OPT_CONF_SUFFIX, " '", my_defaults_group_suffix, "' ", NULL); } } @@ -630,8 +635,8 @@ static ssize_t sst_prepare_other (const char* method, WSREP_SST_OPT_PARENT" '%d'" " %s '%s' ", method, addr_in, mysql_real_data_home, - wsrep_defaults_file, (int)getpid(), - binlog_opt, binlog_opt_val); + wsrep_defaults_file, + (int)getpid(), binlog_opt, binlog_opt_val); my_free(binlog_opt_val); if (ret < 0 || ret >= cmd_len) @@ -913,7 +918,7 @@ static int sst_donate_mysqldump (const char* addr, WSREP_SST_OPT_PORT" '%d' " WSREP_SST_OPT_LPORT" '%u' " WSREP_SST_OPT_SOCKET" '%s' " - " %s " + " '%s' " WSREP_SST_OPT_GTID" '%s:%lld' " WSREP_SST_OPT_GTID_DOMAIN_ID" '%d'" "%s", diff --git a/sql/wsrep_sst.h b/sql/wsrep_sst.h index 460046bc4ad..8bf6dc31464 100644 --- a/sql/wsrep_sst.h +++ b/sql/wsrep_sst.h @@ -27,7 +27,8 @@ #define WSREP_SST_OPT_AUTH "--auth" #define WSREP_SST_OPT_DATA "--datadir" #define WSREP_SST_OPT_CONF "--defaults-file" -#define WSREP_SST_OPT_EXTRA_CONF "--defaults-extra-file" +#define WSREP_SST_OPT_CONF_SUFFIX "--defaults-group-suffix" +#define WSREP_SST_OPT_CONF_EXTRA "--defaults-extra-file" #define WSREP_SST_OPT_PARENT "--parent" #define WSREP_SST_OPT_BINLOG "--binlog" diff --git a/storage/connect/myconn.cpp b/storage/connect/myconn.cpp index 28e6f076e77..e99e089d940 100644 --- a/storage/connect/myconn.cpp +++ b/storage/connect/myconn.cpp @@ -933,8 +933,9 @@ PQRYRES MYSQLC::GetResult(PGLOBAL g, bool pdb) crp->Prec = (crp->Type == TYPE_DOUBLE || crp->Type == TYPE_DECIM) ? fld->decimals : 0; - crp->Length = MY_MAX(fld->length, fld->max_length); - crp->Clen = GetTypeSize(crp->Type, crp->Length); + CHARSET_INFO *cs= get_charset(fld->charsetnr, MYF(0)); + crp->Clen = GetTypeSize(crp->Type, fld->length); + crp->Length = fld->length / (cs ? cs->mbmaxlen : 1); uns = (fld->flags & (UNSIGNED_FLAG | ZEROFILL_FLAG)) ? true : false; if (!(crp->Kdata = AllocValBlock(g, NULL, crp->Type, m_Rows, diff --git a/storage/connect/mysql-test/connect/disabled.def b/storage/connect/mysql-test/connect/disabled.def index 6d59369a4df..0dcf030613d 100644 --- a/storage/connect/mysql-test/connect/disabled.def +++ b/storage/connect/mysql-test/connect/disabled.def @@ -19,3 +19,4 @@ json_java_3 : Need MongoDB running and its Java Driver installed mongo_c : Need MongoDB running and its C Driver installed mongo_java_2 : Need MongoDB running and its Java Driver installed mongo_java_3 : Need MongoDB running and its Java Driver installed +tbl_thread : Bug MDEV-9844,10179,14214 03/01/2018 OB Option THREAD removed diff --git a/storage/connect/tabtbl.cpp b/storage/connect/tabtbl.cpp index 9b83a1c93a5..aa7cf4e41b4 100644 --- a/storage/connect/tabtbl.cpp +++ b/storage/connect/tabtbl.cpp @@ -1,12 +1,9 @@ /************* TabTbl C++ Program Source Code File (.CPP) **************/ /* PROGRAM NAME: TABTBL */ /* ------------- */ -/* Version 1.8 */ +/* Version 1.9 */ /* */ -/* COPYRIGHT: */ -/* ---------- */ -/* (C) Copyright to PlugDB Software Development 2008-2017 */ -/* Author: Olivier BERTRAND */ +/* Author: Olivier BERTRAND 2008-2018 */ /* */ /* WHAT THIS PROGRAM DOES: */ /* ----------------------- */ @@ -168,9 +165,14 @@ PTDB TBLDEF::GetTable(PGLOBAL g, MODE) { if (Catfunc == FNC_COL) return new(g) TDBTBC(this); - else if (Thread) - return new(g) TDBTBM(this); - else + else if (Thread) { +#if defined(DEVELOPMENT) + return new(g) TDBTBM(this); +#else + strcpy(g->Message, "Option THREAD is no more supported"); + return NULL; +#endif // DEVELOPMENT + } else return new(g) TDBTBL(this); } // end of GetTable @@ -560,6 +562,7 @@ void TBTBLK::ReadColumn(PGLOBAL) } // end of ReadColumn +#if defined(DEVELOPMENT) /* ------------------------- Class TDBTBM ---------------------------- */ /***********************************************************************/ @@ -865,5 +868,6 @@ int TDBTBM::ReadNextRemote(PGLOBAL g) return RC_OK; } // end of ReadNextRemote +#endif // DEVELOPMENT /* ------------------------------------------------------------------- */ diff --git a/storage/connect/tabtbl.h b/storage/connect/tabtbl.h index f02bf620aae..e7a84395787 100644 --- a/storage/connect/tabtbl.h +++ b/storage/connect/tabtbl.h @@ -11,30 +11,9 @@ typedef class TBLDEF *PTBLDEF; typedef class TDBTBL *PTDBTBL; -typedef class TDBTBM *PTDBTBM; typedef class MYSQLC *PMYC; /***********************************************************************/ -/* Defines the structures used for distributed TBM tables. */ -/***********************************************************************/ -typedef struct _TBMtable *PTBMT; - -typedef struct _TBMtable { - PTBMT Next; // Points to next data table struct - PTABLE Tap; // Points to the sub table - PGLOBAL G; // Needed in thread routine - bool Complete; // TRUE when all results are read - bool Ready; // TRUE when results are there - int Rows; // Total number of rows read so far - int ProgCur; // Current pos - int ProgMax; // Max pos - int Rc; // Return code - THD *Thd; - pthread_attr_t attr; // ??? - pthread_t Tid; // CheckOpen thread ID - } TBMT; - -/***********************************************************************/ /* TBL table. */ /***********************************************************************/ class DllExport TBLDEF : public PRXDEF { /* Logical table description */ @@ -123,7 +102,33 @@ class TBTBLK : public TIDBLK { protected: // Must not have additional members - }; // end of class TBTBLK +}; // end of class TBTBLK + +#if defined(DEVELOPMENT) +/***********************************************************************/ +/* This table type is buggy and removed until a fix is found. */ +/***********************************************************************/ +typedef class TDBTBM *PTDBTBM; + +/***********************************************************************/ +/* Defines the structures used for distributed TBM tables. */ +/***********************************************************************/ +typedef struct _TBMtable *PTBMT; + +typedef struct _TBMtable { + PTBMT Next; // Points to next data table struct + PTABLE Tap; // Points to the sub table + PGLOBAL G; // Needed in thread routine + bool Complete; // TRUE when all results are read + bool Ready; // TRUE when results are there + int Rows; // Total number of rows read so far + int ProgCur; // Current pos + int ProgMax; // Max pos + int Rc; // Return code + THD *Thd; + pthread_attr_t attr; // ??? + pthread_t Tid; // CheckOpen thread ID +} TBMT; /***********************************************************************/ /* This is the TBM Access Method class declaration. */ @@ -160,3 +165,4 @@ class DllExport TDBTBM : public TDBTBL { }; // end of class TDBTBM pthread_handler_t ThreadOpen(void *p); +#endif // DEVELOPMENT diff --git a/storage/federatedx/ha_federatedx.h b/storage/federatedx/ha_federatedx.h index 02b622b15af..a6bc84bf560 100644 --- a/storage/federatedx/ha_federatedx.h +++ b/storage/federatedx/ha_federatedx.h @@ -169,7 +169,7 @@ public: static void *operator new(size_t size, MEM_ROOT *mem_root) throw () { return alloc_root(mem_root, size); } static void operator delete(void *ptr, size_t size) - { TRASH(ptr, size); } + { TRASH_FREE(ptr, size); } virtual int query(const char *buffer, uint length)=0; virtual FEDERATEDX_IO_RESULT *store_result()=0; diff --git a/storage/heap/ha_heap.cc b/storage/heap/ha_heap.cc index f370b282b07..cb210f4394d 100644 --- a/storage/heap/ha_heap.cc +++ b/storage/heap/ha_heap.cc @@ -91,6 +91,15 @@ ha_heap::ha_heap(handlerton *hton, TABLE_SHARE *table_arg) int ha_heap::open(const char *name, int mode, uint test_if_locked) { + if (table->s->reclength < sizeof (char*)) + { + MEM_UNDEFINED(table->s->default_values + table->s->reclength, + sizeof(char*) - table->s->reclength); + table->s->reclength= sizeof(char*); + MEM_UNDEFINED(table->record[0], table->s->reclength); + MEM_UNDEFINED(table->record[1], table->s->reclength); + } + internal_table= MY_TEST(test_if_locked & HA_OPEN_INTERNAL_TABLE); if (internal_table || (!(file= heap_open(name, mode)) && my_errno == ENOENT)) { diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index d291f6f7c37..1547fa84d7b 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -1,5 +1,5 @@ -# Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. -# Copyright (c) 2014, 2017, MariaDB Corporation +# Copyright (c) 2006, 2017, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2018, MariaDB Corporation. # # 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 @@ -187,3 +187,5 @@ IF(MSVC) ENDIF() ADD_SUBDIRECTORY(${CMAKE_SOURCE_DIR}/extra/mariabackup ${CMAKE_BINARY_DIR}/extra/mariabackup) + +ADD_DEPENDENCIES(innobase GenError) diff --git a/storage/innobase/buf/buf0buddy.cc b/storage/innobase/buf/buf0buddy.cc index d75fc41376d..a1457956767 100644 --- a/storage/innobase/buf/buf0buddy.cc +++ b/storage/innobase/buf/buf0buddy.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2006, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, MariaDB Corporation. 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 @@ -687,7 +688,7 @@ buf_buddy_free_low( buf_pool->buddy_stat[i].used--; recombine: - UNIV_MEM_ASSERT_AND_ALLOC(buf, BUF_BUDDY_LOW << i); + UNIV_MEM_ALLOC(buf, BUF_BUDDY_LOW << i); if (i == BUF_BUDDY_SIZES) { buf_buddy_block_free(buf_pool, buf); diff --git a/storage/innobase/buf/buf0buf.cc b/storage/innobase/buf/buf0buf.cc index 07d3f7efe27..445a6597f7d 100644 --- a/storage/innobase/buf/buf0buf.cc +++ b/storage/innobase/buf/buf0buf.cc @@ -2,7 +2,7 @@ Copyright (c) 1995, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. -Copyright (c) 2013, 2017, MariaDB Corporation. +Copyright (c) 2013, 2018, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -3141,11 +3141,26 @@ buf_pool_clear_hash_index() see the comments in buf0buf.h */ if (!index) { +# if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG + ut_a(!block->n_pointers); +# endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ continue; } - ut_ad(buf_block_get_state(block) - == BUF_BLOCK_FILE_PAGE); + ut_d(buf_page_state state + = buf_block_get_state(block)); + /* Another thread may have set the + state to BUF_BLOCK_REMOVE_HASH in + buf_LRU_block_remove_hashed(). + + The state change in buf_page_realloc() + is not observable here, because in + that case we would have !block->index. + + In the end, the entire adaptive hash + index will be removed. */ + ut_ad(state == BUF_BLOCK_FILE_PAGE + || state == BUF_BLOCK_REMOVE_HASH); # if defined UNIV_AHI_DEBUG || defined UNIV_DEBUG block->n_pointers = 0; # endif /* UNIV_AHI_DEBUG || UNIV_DEBUG */ diff --git a/storage/innobase/buf/buf0lru.cc b/storage/innobase/buf/buf0lru.cc index 2d68b8e9ccd..cdea41ff191 100644 --- a/storage/innobase/buf/buf0lru.cc +++ b/storage/innobase/buf/buf0lru.cc @@ -1883,7 +1883,7 @@ buf_LRU_block_free_non_file_page( ut_d(block->page.in_free_list = TRUE); } - UNIV_MEM_ASSERT_AND_FREE(block->frame, UNIV_PAGE_SIZE); + UNIV_MEM_FREE(block->frame, UNIV_PAGE_SIZE); } /******************************************************************//** diff --git a/storage/innobase/data/data0type.cc b/storage/innobase/data/data0type.cc index d4b809c3f59..54cdfa35803 100644 --- a/storage/innobase/data/data0type.cc +++ b/storage/innobase/data/data0type.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2015, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -44,8 +44,10 @@ ulint dtype_get_at_most_n_mbchars( /*========================*/ ulint prtype, /*!< in: precise type */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of - a multi-byte character */ + ulint mbminlen, /*!< in: minimum length of + a multi-byte character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of + a multi-byte character, in bytes */ ulint prefix_len, /*!< in: length of the requested prefix, in characters, multiplied by dtype_get_mbmaxlen(dtype) */ @@ -53,9 +55,6 @@ dtype_get_at_most_n_mbchars( const char* str) /*!< in: the string whose prefix length is being determined */ { - ulint mbminlen = DATA_MBMINLEN(mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN(mbminmaxlen); - ut_a(data_len != UNIV_SQL_NULL); ut_ad(!mbmaxlen || !(prefix_len % mbmaxlen)); diff --git a/storage/innobase/dict/dict0mem.cc b/storage/innobase/dict/dict0mem.cc index 86a2e025c8f..ba3fa177572 100644 --- a/storage/innobase/dict/dict0mem.cc +++ b/storage/innobase/dict/dict0mem.cc @@ -2,7 +2,7 @@ Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2017, MariaDB Corporation. +Copyright (c) 2013, 2018, MariaDB Corporation. 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 @@ -447,8 +447,8 @@ dict_mem_table_col_rename_low( ut_ad(from_len <= NAME_LEN); ut_ad(to_len <= NAME_LEN); - char from[NAME_LEN]; - strncpy(from, s, NAME_LEN); + char from[NAME_LEN + 1]; + strncpy(from, s, NAME_LEN + 1); if (from_len == to_len) { /* The easy case: simply replace the column name in @@ -675,9 +675,9 @@ dict_mem_fill_column_struct( column->mtype = (unsigned int) mtype; column->prtype = (unsigned int) prtype; column->len = (unsigned int) col_len; - - dtype_get_mblen(mtype, prtype, &mbminlen, &mbmaxlen); - dict_col_set_mbminmaxlen(column, mbminlen, mbmaxlen); + dtype_get_mblen(mtype, prtype, &mbminlen, &mbmaxlen); + column->mbminlen = mbminlen; + column->mbmaxlen = mbmaxlen; } /**********************************************************************//** diff --git a/storage/innobase/fil/fil0fil.cc b/storage/innobase/fil/fil0fil.cc index 6c933e58803..057aa37cabe 100644 --- a/storage/innobase/fil/fil0fil.cc +++ b/storage/innobase/fil/fil0fil.cc @@ -2109,7 +2109,7 @@ fil_write_flushed_lsn( { byte* buf1; byte* buf; - dberr_t err; + dberr_t err = DB_TABLESPACE_NOT_FOUND; buf1 = static_cast<byte*>(ut_malloc_nokey(2 * UNIV_PAGE_SIZE)); buf = static_cast<byte*>(ut_align(buf1, UNIV_PAGE_SIZE)); diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index c07f205305c..b29f52072d2 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2017, MariaDB Corporation. +Copyright (c) 2016, 2018, MariaDB Corporation. 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 @@ -2005,7 +2005,7 @@ fts_create_one_index_table( ? DATA_VARCHAR : DATA_VARMYSQL, field->col->prtype, FTS_MAX_WORD_LEN_IN_CHAR - * DATA_MBMAXLEN(field->col->mbminmaxlen)); + * field->col->mbmaxlen); dict_mem_table_add_col(new_table, heap, "first_doc_id", DATA_INT, DATA_NOT_NULL | DATA_UNSIGNED, @@ -4556,10 +4556,17 @@ fts_add_token( t_str.f_str = static_cast<byte*>( mem_heap_alloc(heap, t_str.f_len)); - newlen = innobase_fts_casedn_str( - result_doc->charset, - reinterpret_cast<char*>(str.f_str), str.f_len, - reinterpret_cast<char*>(t_str.f_str), t_str.f_len); + /* For binary collations, a case sensitive search is + performed. Hence don't convert to lower case. */ + if (my_binary_compare(result_doc->charset)) { + memcpy(t_str.f_str, str.f_str, str.f_len); + t_str.f_str[str.f_len]= 0; + newlen= str.f_len; + } else { + newlen = innobase_fts_casedn_str( + result_doc->charset, (char*) str.f_str, str.f_len, + (char*) t_str.f_str, t_str.f_len); + } t_str.f_len = newlen; t_str.f_str[newlen] = 0; @@ -7514,8 +7521,7 @@ fts_init_recover_doc( &doc.text.f_len, static_cast<byte*>(dfield_get_data(dfield)), dict_table_page_size(table), len, - static_cast<mem_heap_t*>(doc.self_heap->arg) - ); + static_cast<mem_heap_t*>(doc.self_heap->arg)); } else { doc.text.f_str = static_cast<byte*>( dfield_get_data(dfield)); diff --git a/storage/innobase/fts/fts0que.cc b/storage/innobase/fts/fts0que.cc index 1b03e041871..b9977bd31e5 100644 --- a/storage/innobase/fts/fts0que.cc +++ b/storage/innobase/fts/fts0que.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2007, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -2017,8 +2017,7 @@ fts_query_fetch_document( if (dfield_is_ext(dfield)) { data = btr_copy_externally_stored_field( &cur_len, data, phrase->page_size, - dfield_get_len(dfield), phrase->heap - ); + dfield_get_len(dfield), phrase->heap); } else { cur_len = dfield_get_len(dfield); } @@ -4030,9 +4029,17 @@ fts_query( lc_query_str_len = query_len * charset->casedn_multiply + 1; lc_query_str = static_cast<byte*>(ut_malloc_nokey(lc_query_str_len)); + /* For binary collations, a case sensitive search is + performed. Hence don't convert to lower case. */ + if (my_binary_compare(charset)) { + memcpy(lc_query_str, query_str, query_len); + lc_query_str[query_len]= 0; + result_len= query_len; + } else { result_len = innobase_fts_casedn_str( - charset, (char*) query_str, query_len, - (char*) lc_query_str, lc_query_str_len); + charset, (char*)( query_str), query_len, + (char*)(lc_query_str), lc_query_str_len); + } ut_ad(result_len < lc_query_str_len); diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index 1a01c78a069..de81a696eca 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -13765,25 +13765,6 @@ innobase_rename_table( error = row_rename_table_for_mysql(norm_from, norm_to, trx, TRUE); - if (error == DB_TABLE_NOT_FOUND) { - /* May be partitioned table, which consists of partitions - named table_name#P#partition_name[#SP#subpartition_name]. - - We are doing a DDL operation. */ - ++trx->will_lock; - trx_start_if_not_started(trx, true); - error = row_rename_partitions_for_mysql(norm_from, norm_to, - trx); - if (error == DB_TABLE_NOT_FOUND) { - ib::error() << "Table " << ut_get_name(trx, norm_from) - << " does not exist in the InnoDB internal" - " data dictionary though MariaDB is trying to" - " rename the table. Have you copied the .frm" - " file of the table to the MariaDB database" - " directory from another database? " - << TROUBLESHOOTING_MSG; - } - } if (error != DB_SUCCESS) { if (error == DB_TABLE_NOT_FOUND && innobase_get_lower_case_table_names() == 1) { @@ -22235,7 +22216,7 @@ innobase_get_computed_value( if (max_prefix) { len = dtype_get_at_most_n_mbchars( col->m_col.prtype, - col->m_col.mbminmaxlen, + col->m_col.mbminlen, col->m_col.mbmaxlen, max_prefix, field->len, static_cast<char*>(dfield_get_data(field))); @@ -22573,8 +22554,19 @@ innodb_buffer_pool_size_validate( *static_cast<longlong*>(save) = requested_buf_pool_size; + if (srv_buf_pool_size == static_cast<ulint>(intbuf)) { + buf_pool_mutex_exit_all(); + /* nothing to do */ + return(0); + } + if (srv_buf_pool_size == requested_buf_pool_size) { buf_pool_mutex_exit_all(); + push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, + ER_WRONG_ARGUMENTS, + "innodb_buffer_pool_size must be at least" + " innodb_buffer_pool_chunk_size=%lu", + srv_buf_pool_chunk_unit); /* nothing to do */ return(0); } diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index 87f1af6ec7f..0f0534853a8 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2017, MariaDB Corporation. +Copyright (c) 2013, 2018, MariaDB Corporation. 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 @@ -1756,8 +1756,7 @@ innobase_col_to_mysql( #ifdef UNIV_DEBUG case DATA_MYSQL: ut_ad(flen >= len); - ut_ad(DATA_MBMAXLEN(col->mbminmaxlen) - >= DATA_MBMINLEN(col->mbminmaxlen)); + ut_ad(col->mbmaxlen >= col->mbminlen); memcpy(dest, data, len); break; diff --git a/storage/innobase/include/data0type.h b/storage/innobase/include/data0type.h index 35dcf2f3397..c4521d0723b 100644 --- a/storage/innobase/include/data0type.h +++ b/storage/innobase/include/data0type.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -199,16 +199,7 @@ store the charset-collation number; one byte is left unused, though */ #define DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE 6 /* Maximum multi-byte character length in bytes, plus 1 */ -#define DATA_MBMAX 5 - -/* Pack mbminlen, mbmaxlen to mbminmaxlen. */ -#define DATA_MBMINMAXLEN(mbminlen, mbmaxlen) \ - unsigned((mbmaxlen) * DATA_MBMAX + (mbminlen)) -/* Get mbminlen from mbminmaxlen. */ -#define DATA_MBMINLEN(mbminmaxlen) \ - unsigned(UNIV_EXPECT((mbminmaxlen) % DATA_MBMAX, 1)) -/* Get mbmaxlen from mbminmaxlen. */ -#define DATA_MBMAXLEN(mbminmaxlen) unsigned((mbminmaxlen) / DATA_MBMAX) +#define DATA_MBMAX 8 /* For checking if mtype is GEOMETRY datatype */ #define DATA_GEOMETRY_MTYPE(mtype) ((mtype) == DATA_GEOMETRY) @@ -251,8 +242,10 @@ ulint dtype_get_at_most_n_mbchars( /*========================*/ ulint prtype, /*!< in: precise type */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of - a multi-byte character */ + ulint mbminlen, /*!< in: minimum length of + a multi-byte character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of + a multi-byte character, in bytes */ ulint prefix_len, /*!< in: length of the requested prefix, in characters, multiplied by dtype_get_mbmaxlen(dtype) */ @@ -395,19 +388,6 @@ ulint dtype_get_mbmaxlen( /*===============*/ const dtype_t* type); /*!< in: type */ -/*********************************************************************//** -Sets the minimum and maximum length of a character, in bytes. */ -UNIV_INLINE -void -dtype_set_mbminmaxlen( -/*==================*/ - dtype_t* type, /*!< in/out: type */ - ulint mbminlen, /*!< in: minimum length of a char, - in bytes, or 0 if this is not - a character type */ - ulint mbmaxlen); /*!< in: maximum length of a char, - in bytes, or 0 if this is not - a character type */ /***********************************************************************//** Returns the size of a fixed size data type, 0 if not a fixed size type. @return fixed size, or 0 */ @@ -418,7 +398,9 @@ dtype_get_fixed_size_low( ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ ulint len, /*!< in: length */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of a + ulint mbminlen, /*!< in: minimum length of a + multibyte character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of a multibyte character, in bytes */ ulint comp); /*!< in: nonzero=ROW_FORMAT=COMPACT */ @@ -432,8 +414,8 @@ dtype_get_min_size_low( ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ ulint len, /*!< in: length */ - ulint mbminmaxlen); /*!< in: minimum and maximum length of a - multibyte character */ + ulint mbminlen, /*!< in: minimum length of a character */ + ulint mbmaxlen); /*!< in: maximum length of a character */ /***********************************************************************//** Returns the maximum size of a data type. Note: types in system tables may be incomplete and return incorrect information. @@ -545,11 +527,10 @@ struct dtype_t{ string data (in addition to the string, MySQL uses 1 or 2 bytes to store the string length) */ - unsigned mbminmaxlen:5; /*!< minimum and maximum length of a - character, in bytes; - DATA_MBMINMAXLEN(mbminlen,mbmaxlen); - mbminlen=DATA_MBMINLEN(mbminmaxlen); - mbmaxlen=DATA_MBMINLEN(mbminmaxlen) */ + unsigned mbminlen:3; /*!< minimum length of a character, + in bytes */ + unsigned mbmaxlen:3; /*!< maximum length of a character, + in bytes */ }; #include "data0type.ic" diff --git a/storage/innobase/include/data0type.ic b/storage/innobase/include/data0type.ic index 0af2dcf9fa1..c0b32953cff 100644 --- a/storage/innobase/include/data0type.ic +++ b/storage/innobase/include/data0type.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -101,27 +101,6 @@ dtype_get_mblen( } /*********************************************************************//** -Sets the minimum and maximum length of a character, in bytes. */ -UNIV_INLINE -void -dtype_set_mbminmaxlen( -/*==================*/ - dtype_t* type, /*!< in/out: type */ - ulint mbminlen, /*!< in: minimum length of a char, - in bytes, or 0 if this is not - a character type */ - ulint mbmaxlen) /*!< in: maximum length of a char, - in bytes, or 0 if this is not - a character type */ -{ - ut_ad(mbminlen < DATA_MBMAX); - ut_ad(mbmaxlen < DATA_MBMAX); - ut_ad(mbminlen <= mbmaxlen); - - type->mbminmaxlen = DATA_MBMINMAXLEN(mbminlen, mbmaxlen); -} - -/*********************************************************************//** Compute the mbminlen and mbmaxlen members of a data type structure. */ UNIV_INLINE void @@ -133,7 +112,8 @@ dtype_set_mblen( ulint mbmaxlen; dtype_get_mblen(type->mtype, type->prtype, &mbminlen, &mbmaxlen); - dtype_set_mbminmaxlen(type, mbminlen, mbmaxlen); + type->mbminlen = mbminlen; + type->mbmaxlen = mbmaxlen; ut_ad(dtype_validate(type)); } @@ -225,8 +205,7 @@ dtype_get_mbminlen( /*===============*/ const dtype_t* type) /*!< in: type */ { - ut_ad(type); - return(DATA_MBMINLEN(type->mbminmaxlen)); + return type->mbminlen; } /*********************************************************************//** Gets the maximum length of a character, in bytes. @@ -238,8 +217,7 @@ dtype_get_mbmaxlen( /*===============*/ const dtype_t* type) /*!< in: type */ { - ut_ad(type); - return(DATA_MBMAXLEN(type->mbminmaxlen)); + return type->mbmaxlen; } /**********************************************************************//** @@ -477,8 +455,10 @@ dtype_get_fixed_size_low( ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ ulint len, /*!< in: length */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of - a multibyte character, in bytes */ + ulint mbminlen, /*!< in: minimum length of a + multibyte character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of a + multibyte character, in bytes */ ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ { switch (mtype) { @@ -518,11 +498,10 @@ dtype_get_fixed_size_low( dtype_get_charset_coll(prtype), &i_mbminlen, &i_mbmaxlen); - ut_ad(DATA_MBMINMAXLEN(i_mbminlen, i_mbmaxlen) - == mbminmaxlen); + ut_ad(i_mbminlen == mbminlen); + ut_ad(i_mbmaxlen == mbmaxlen); #endif /* UNIV_DEBUG */ - if (DATA_MBMINLEN(mbminmaxlen) - == DATA_MBMAXLEN(mbminmaxlen)) { + if (mbminlen == mbmaxlen) { return(len); } } @@ -552,8 +531,8 @@ dtype_get_min_size_low( ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ ulint len, /*!< in: length */ - ulint mbminmaxlen) /*!< in: minimum and maximum length of a - multi-byte character */ + ulint mbminlen, /*!< in: minimum length of a character */ + ulint mbmaxlen) /*!< in: maximum length of a character */ { switch (mtype) { case DATA_SYS: @@ -583,9 +562,6 @@ dtype_get_min_size_low( if (prtype & DATA_BINARY_TYPE) { return(len); } else { - ulint mbminlen = DATA_MBMINLEN(mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN(mbminmaxlen); - if (mbminlen == mbmaxlen) { return(len); } @@ -656,5 +632,5 @@ dtype_get_sql_null_size( ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ { return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len, - type->mbminmaxlen, comp)); + type->mbminlen, type->mbmaxlen, comp)); } diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 60c100e80ca..b22e38d4bd0 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -2,7 +2,7 @@ Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2017, MariaDB Corporation. +Copyright (c) 2013, 2018, MariaDB Corporation. 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 @@ -182,18 +182,6 @@ dict_col_get_mbmaxlen( const dict_col_t* col) /*!< in: column */ MY_ATTRIBUTE((nonnull, warn_unused_result)); /*********************************************************************//** -Sets the minimum and maximum number of bytes per character. */ -UNIV_INLINE -void -dict_col_set_mbminmaxlen( -/*=====================*/ - dict_col_t* col, /*!< in/out: column */ - ulint mbminlen, /*!< in: minimum multi-byte - character size, in bytes */ - ulint mbmaxlen) /*!< in: minimum multi-byte - character size, in bytes */ - MY_ATTRIBUTE((nonnull)); -/*********************************************************************//** Gets the column data type. */ UNIV_INLINE void diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index 4efb0971209..fd54f772958 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2017, MariaDB Corporation. +Copyright (c) 2013, 2018, MariaDB Corporation. 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 @@ -41,7 +41,7 @@ dict_col_get_mbminlen( /*==================*/ const dict_col_t* col) /*!< in: column */ { - return(DATA_MBMINLEN(col->mbminmaxlen)); + return col->mbminlen; } /*********************************************************************//** Gets the maximum number of bytes per character. @@ -52,25 +52,7 @@ dict_col_get_mbmaxlen( /*==================*/ const dict_col_t* col) /*!< in: column */ { - return(DATA_MBMAXLEN(col->mbminmaxlen)); -} -/*********************************************************************//** -Sets the minimum and maximum number of bytes per character. */ -UNIV_INLINE -void -dict_col_set_mbminmaxlen( -/*=====================*/ - dict_col_t* col, /*!< in/out: column */ - ulint mbminlen, /*!< in: minimum multi-byte - character size, in bytes */ - ulint mbmaxlen) /*!< in: minimum multi-byte - character size, in bytes */ -{ - ut_ad(mbminlen < DATA_MBMAX); - ut_ad(mbmaxlen < DATA_MBMAX); - ut_ad(mbminlen <= mbmaxlen); - - col->mbminmaxlen = DATA_MBMINMAXLEN(mbminlen, mbmaxlen); + return col->mbmaxlen; } /*********************************************************************//** Gets the column data type. */ @@ -87,7 +69,8 @@ dict_col_copy_type( type->mtype = col->mtype; type->prtype = col->prtype; type->len = col->len; - type->mbminmaxlen = col->mbminmaxlen; + type->mbminlen = col->mbminlen; + type->mbmaxlen = col->mbmaxlen; } /** Check if a column is a virtual column @param[in] col column @@ -117,7 +100,8 @@ dict_col_type_assert_equal( ut_ad(col->mtype == type->mtype); ut_ad(col->prtype == type->prtype); //ut_ad(col->len == type->len); - ut_ad(col->mbminmaxlen == type->mbminmaxlen); + ut_ad(col->mbminlen == type->mbminlen); + ut_ad(col->mbmaxlen == type->mbmaxlen); return(TRUE); } @@ -133,7 +117,7 @@ dict_col_get_min_size( const dict_col_t* col) /*!< in: column */ { return(dtype_get_min_size_low(col->mtype, col->prtype, col->len, - col->mbminmaxlen)); + col->mbminlen, col->mbmaxlen)); } /***********************************************************************//** Returns the maximum size of the column. @@ -157,7 +141,7 @@ dict_col_get_fixed_size( ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ { return(dtype_get_fixed_size_low(col->mtype, col->prtype, col->len, - col->mbminmaxlen, comp)); + col->mbminlen, col->mbmaxlen, comp)); } /***********************************************************************//** Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column. diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index e8402cdaf95..4bc08942164 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -2,7 +2,7 @@ Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2017, MariaDB Corporation. +Copyright (c) 2013, 2018, MariaDB Corporation. 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 @@ -297,7 +297,7 @@ result in recursive cascading calls. This defines the maximum number of such cascading deletes/updates allowed. When exceeded, the delete from parent table will fail, and user has to drop excessive foreign constraint before proceeds. */ -#define FK_MAX_CASCADE_DEL 255 +#define FK_MAX_CASCADE_DEL 15 /**********************************************************************//** Creates a table memory object. @@ -616,11 +616,10 @@ struct dict_col_t{ the string, MySQL uses 1 or 2 bytes to store the string length) */ - unsigned mbminmaxlen:5; /*!< minimum and maximum length of a - character, in bytes; - DATA_MBMINMAXLEN(mbminlen,mbmaxlen); - mbminlen=DATA_MBMINLEN(mbminmaxlen); - mbmaxlen=DATA_MBMINLEN(mbminmaxlen) */ + unsigned mbminlen:3; /*!< minimum length of a + character, in bytes */ + unsigned mbmaxlen:3; /*!< maximum length of a + character, in bytes */ /*----------------------*/ /* End of definitions copied from dtype_t */ /* @} */ diff --git a/storage/innobase/include/mem0mem.ic b/storage/innobase/include/mem0mem.ic index a8292a16143..4d76f07694d 100644 --- a/storage/innobase/include/mem0mem.ic +++ b/storage/innobase/include/mem0mem.ic @@ -280,8 +280,7 @@ mem_heap_free_heap_top( mem_block_set_free(block, old_top - (byte*) block); ut_ad(mem_block_get_start(block) <= mem_block_get_free(block)); - UNIV_MEM_ASSERT_W(old_top, (byte*) block + block->len - old_top); - UNIV_MEM_ALLOC(old_top, (byte*) block + block->len - old_top); + UNIV_MEM_FREE(old_top, (byte*) block + block->len - old_top); /* If free == start, we may free the block if it is not the first one */ @@ -445,7 +444,6 @@ mem_heap_free_top( /* Subtract the free field of block */ mem_block_set_free(block, mem_block_get_free(block) - MEM_SPACE_NEEDED(n)); - UNIV_MEM_ASSERT_W((byte*) block + mem_block_get_free(block), n); /* If free == start, we may free the block if it is not the first one */ @@ -454,11 +452,7 @@ mem_heap_free_top( == mem_block_get_start(block))) { mem_heap_block_free(heap, block); } else { - /* Avoid a bogus UNIV_MEM_ASSERT_W() warning in a - subsequent invocation of mem_heap_free_top(). - Originally, this was UNIV_MEM_FREE(), to catch writes - to freed memory. */ - UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n); + UNIV_MEM_FREE((byte*) block + mem_block_get_free(block), n); } } diff --git a/storage/innobase/include/mtr0mtr.h b/storage/innobase/include/mtr0mtr.h index 2c527a0980b..6639a3448ea 100644 --- a/storage/innobase/include/mtr0mtr.h +++ b/storage/innobase/include/mtr0mtr.h @@ -32,7 +32,6 @@ Created 11/26/1995 Heikki Tuuri #include "log0types.h" #include "mtr0types.h" #include "buf0types.h" -#include "trx0types.h" #include "dyn0buf.h" /** Start a mini-transaction. */ @@ -320,7 +319,7 @@ struct mtr_t { the same set of tablespaces as this one */ void set_spaces(const mtr_t& mtr) { - ut_ad(m_impl.m_user_space_id == TRX_SYS_SPACE); + ut_ad(!m_impl.m_user_space_id); ut_ad(!m_impl.m_user_space); ut_ad(!m_impl.m_undo_space); ut_ad(!m_impl.m_sys_space); @@ -337,9 +336,9 @@ struct mtr_t { @return the tablespace */ fil_space_t* set_named_space(ulint space_id) { - ut_ad(m_impl.m_user_space_id == TRX_SYS_SPACE); + ut_ad(!m_impl.m_user_space_id); ut_d(m_impl.m_user_space_id = space_id); - if (space_id == TRX_SYS_SPACE) { + if (!space_id) { return(set_sys_modified()); } else { lookup_user_space(space_id); diff --git a/storage/innobase/include/rem0rec.ic b/storage/innobase/include/rem0rec.ic index e16eab62181..cb1f0d9836f 100644 --- a/storage/innobase/include/rem0rec.ic +++ b/storage/innobase/include/rem0rec.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2015, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, MariaDB Corporation. 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 @@ -960,7 +961,7 @@ rec_offs_set_n_alloc( { ut_ad(offsets); ut_ad(n_alloc > REC_OFFS_HEADER_SIZE); - UNIV_MEM_ASSERT_AND_ALLOC(offsets, n_alloc * sizeof *offsets); + UNIV_MEM_ALLOC(offsets, n_alloc * sizeof *offsets); offsets[0] = n_alloc; } diff --git a/storage/innobase/include/row0mysql.h b/storage/innobase/include/row0mysql.h index 420786dfed3..bc537dac4c9 100644 --- a/storage/innobase/include/row0mysql.h +++ b/storage/innobase/include/row0mysql.h @@ -297,6 +297,18 @@ row_create_update_node_for_mysql( /*=============================*/ dict_table_t* table, /*!< in: table to update */ mem_heap_t* heap); /*!< in: mem heap from which allocated */ + +/**********************************************************************//** +Does a cascaded delete or set null in a foreign key operation. +@return error code or DB_SUCCESS */ +dberr_t +row_update_cascade_for_mysql( +/*=========================*/ + que_thr_t* thr, /*!< in: query thread */ + upd_node_t* node, /*!< in: update node used in the cascade + or set null operation */ + dict_table_t* table) /*!< in: table where we do the operation */ + MY_ATTRIBUTE((nonnull, warn_unused_result)); /*********************************************************************//** Locks the data dictionary exclusively for performing a table create or other data dictionary modification operation. */ @@ -498,18 +510,6 @@ row_rename_table_for_mysql( bool commit) /*!< in: whether to commit trx */ MY_ATTRIBUTE((nonnull, warn_unused_result)); -/** Renames a partitioned table for MySQL. -@param[in] old_name Old table name. -@param[in] new_name New table name. -@param[in,out] trx Transaction. -@return error code or DB_SUCCESS */ -dberr_t -row_rename_partitions_for_mysql( - const char* old_name, - const char* new_name, - trx_t* trx) - MY_ATTRIBUTE((nonnull, warn_unused_result)); - /*********************************************************************//** Scans an index for either COOUNT(*) or CHECK TABLE. If CHECK TABLE; Checks that the index contains entries in an ascending order, diff --git a/storage/innobase/include/row0upd.h b/storage/innobase/include/row0upd.h index ec7995dd096..a174fd03751 100644 --- a/storage/innobase/include/row0upd.h +++ b/storage/innobase/include/row0upd.h @@ -32,20 +32,10 @@ Created 12/27/1996 Heikki Tuuri #include "btr0types.h" #include "dict0types.h" #include "trx0types.h" -#include <stack> #include "btr0pcur.h" #include "que0types.h" #include "pars0types.h" -/** The std::deque to store cascade update nodes, that uses mem_heap_t -as allocator. */ -typedef std::deque<upd_node_t*, mem_heap_allocator<upd_node_t*> > - deque_mem_heap_t; - -/** Double-ended queue of update nodes to be processed for cascade -operations */ -typedef deque_mem_heap_t upd_cascade_t; - /*********************************************************************//** Creates an update vector object. @return own: update vector object */ @@ -523,38 +513,12 @@ struct upd_node_t{ dict_foreign_t* foreign;/* NULL or pointer to a foreign key constraint if this update node is used in doing an ON DELETE or ON UPDATE operation */ - - bool cascade_top; - /*!< true if top level in cascade */ - - upd_cascade_t* cascade_upd_nodes; - /*!< Queue of update nodes to handle the - cascade of update and delete operations in an - iterative manner. Their parent/child - relations are properly maintained. All update - nodes point to this same queue. All these - nodes are allocated in heap pointed to by - upd_node_t::cascade_heap. */ - - upd_cascade_t* new_upd_nodes; - /*!< Intermediate list of update nodes in a - cascading update/delete operation. After - processing one update node, this will be - concatenated to cascade_upd_nodes. This extra - list is needed so that retry because of - DB_LOCK_WAIT works corrrectly. */ - - upd_cascade_t* processed_cascades; - /*!< List of processed update nodes in a - cascading update/delete operation. All the - cascade nodes are stored here, so that memory - can be freed. */ - + upd_node_t* cascade_node;/* NULL or an update node template which + is used to implement ON DELETE/UPDATE CASCADE + or ... SET NULL for foreign keys */ mem_heap_t* cascade_heap; - /*!< NULL or a mem heap where cascade_upd_nodes - are created. This heap is owned by the node - that has cascade_top=true. */ - + /*!< NULL or a mem heap where cascade + node is created.*/ sel_node_t* select; /*!< query graph subtree implementing a base table cursor: the rows returned will be updated */ @@ -601,25 +565,8 @@ struct upd_node_t{ sym_node_t* table_sym;/* table node in symbol table */ que_node_t* col_assign_list; /* column assignment list */ - - doc_id_t fts_doc_id; - /* The FTS doc id of the row that is now - pointed to by the pcur. */ - - doc_id_t fts_next_doc_id; - /* The new fts doc id that will be used - in update operation */ - ulint magic_n; -#ifndef DBUG_OFF - /** Print information about this object into the trace log file. */ - void dbug_trace(); - - /** Ensure that the member cascade_upd_nodes has only one update node - for each of the tables. This is useful for testing purposes. */ - void check_cascade_only_once(); -#endif /* !DBUG_OFF */ }; #define UPD_NODE_MAGIC_N 1579975 diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index ce124f2fe11..d9f26319de6 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2017, MariaDB Corporation. +Copyright (c) 2013, 2018, MariaDB Corporation. Copyright (c) 2008, Google Inc. Portions of this file contain modifications contributed and copyrighted by @@ -41,7 +41,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_MAJOR 5 #define INNODB_VERSION_MINOR 7 -#define INNODB_VERSION_BUGFIX 20 +#define INNODB_VERSION_BUGFIX 21 /* The following is the InnoDB version as shown in SELECT plugin_version FROM information_schema.plugins; @@ -671,14 +671,6 @@ typedef void* os_thread_ret_t; # define UNIV_MEM_ASSERT_W(addr, size) do {} while(0) # define UNIV_MEM_TRASH(addr, c, size) do {} while(0) #endif -#define UNIV_MEM_ASSERT_AND_FREE(addr, size) do { \ - UNIV_MEM_ASSERT_W(addr, size); \ - UNIV_MEM_FREE(addr, size); \ -} while (0) -#define UNIV_MEM_ASSERT_AND_ALLOC(addr, size) do { \ - UNIV_MEM_ASSERT_W(addr, size); \ - UNIV_MEM_ALLOC(addr, size); \ -} while (0) extern ulong srv_page_size_shift; extern ulong srv_page_size; diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index f25ac596d5f..ca20a5033dc 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -1,7 +1,7 @@ /***************************************************************************** -Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2017, MariaDB Corporation. +Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2014, 2018, MariaDB Corporation. 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 @@ -2728,7 +2728,10 @@ RecLock::lock_add_priority( lock_t* grant_position = NULL; lock_t* add_position = NULL; - HASH_SEARCH(hash, lock_sys->rec_hash, m_rec_id.fold(), lock_t*, + /* Different lock (such as predicate lock) are on different hash */ + hash_table_t* lock_hash = lock_hash_get(m_mode); + + HASH_SEARCH(hash, lock_hash, m_rec_id.fold(), lock_t*, lock_head, ut_ad(lock_head->is_record_lock()), true); ut_ad(lock_head); @@ -6444,7 +6447,7 @@ lock_rec_block_validate( /* Make sure that the tablespace is not deleted while we are trying to access the page. */ - if (fil_space_t* space = fil_space_acquire(space_id)) { + if (fil_space_t* space = fil_space_acquire_silent(space_id)) { dberr_t err = DB_SUCCESS; mtr_start(&mtr); diff --git a/storage/innobase/mem/mem0mem.cc b/storage/innobase/mem/mem0mem.cc index a5b5c9e0f84..ca83891d459 100644 --- a/storage/innobase/mem/mem0mem.cc +++ b/storage/innobase/mem/mem0mem.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2014, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -432,15 +432,11 @@ mem_heap_block_free( len = block->len; block->magic_n = MEM_FREED_BLOCK_MAGIC_N; - UNIV_MEM_ASSERT_W(block, len); - if (type == MEM_HEAP_DYNAMIC || len < UNIV_PAGE_SIZE / 2) { - ut_ad(!buf_block); ut_free(block); } else { ut_ad(type & MEM_HEAP_BUFFER); - buf_block_free(buf_block); } } diff --git a/storage/innobase/que/que0que.cc b/storage/innobase/que/que0que.cc index a45ac188f2f..47c41519b40 100644 --- a/storage/innobase/que/que0que.cc +++ b/storage/innobase/que/que0que.cc @@ -482,20 +482,17 @@ que_graph_free_recursive( case QUE_NODE_UPDATE: upd = static_cast<upd_node_t*>(node); - DBUG_PRINT("que_graph_free_recursive", - ("QUE_NODE_UPDATE: %p, processed_cascades: %p", - upd, upd->processed_cascades)); - if (upd->in_mysql_interface) { btr_pcur_free_for_mysql(upd->pcur); upd->in_mysql_interface = FALSE; } - if (upd->cascade_top) { + que_graph_free_recursive(upd->cascade_node); + + if (upd->cascade_heap) { mem_heap_free(upd->cascade_heap); upd->cascade_heap = NULL; - upd->cascade_top = false; } que_graph_free_recursive(upd->select); diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc index 6cd8db5d37b..562dc53e9f8 100644 --- a/storage/innobase/rem/rem0rec.cc +++ b/storage/innobase/rem/rem0rec.cc @@ -894,21 +894,18 @@ rec_get_converted_size_comp_prefix_low( if (fixed_len) { #ifdef UNIV_DEBUG - ulint mbminlen = DATA_MBMINLEN(col->mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN(col->mbminmaxlen); - ut_ad(len <= fixed_len); if (dict_index_is_spatial(index)) { ut_ad(type->mtype == DATA_SYS_CHILD - || !mbmaxlen - || len >= mbminlen * (fixed_len - / mbmaxlen)); + || !col->mbmaxlen + || len >= col->mbminlen + * fixed_len / col->mbmaxlen); } else { ut_ad(type->mtype != DATA_SYS_CHILD); - ut_ad(!mbmaxlen - || len >= mbminlen * (fixed_len - / mbmaxlen)); + ut_ad(!col->mbmaxlen + || len >= col->mbminlen + * fixed_len / col->mbmaxlen); } /* dict_index_add_col() should guarantee this */ @@ -1296,15 +1293,11 @@ rec_convert_dtuple_to_rec_comp( 0..127. The length will be encoded in two bytes when it is 128 or more, or when the field is stored externally. */ if (fixed_len) { -#ifdef UNIV_DEBUG - ulint mbminlen = DATA_MBMINLEN(col->mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN(col->mbminmaxlen); - ut_ad(len <= fixed_len); - ut_ad(!mbmaxlen || len >= mbminlen - * (fixed_len / mbmaxlen)); + ut_ad(!col->mbmaxlen + || len >= col->mbminlen + * fixed_len / col->mbmaxlen); ut_ad(!dfield_is_ext(field)); -#endif /* UNIV_DEBUG */ } else if (dfield_is_ext(field)) { ut_ad(DATA_BIG_COL(col)); ut_ad(len <= REC_ANTELOPE_MAX_INDEX_COL_LEN diff --git a/storage/innobase/row/row0ftsort.cc b/storage/innobase/row/row0ftsort.cc index dad00c58827..0a937847c33 100644 --- a/storage/innobase/row/row0ftsort.cc +++ b/storage/innobase/row/row0ftsort.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2010, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2017, MariaDB Corporation. +Copyright (c) 2015, 2018, MariaDB Corporation. 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 @@ -108,8 +108,9 @@ row_merge_create_fts_sort_index( field->col->prtype = idx_field->col->prtype | DATA_NOT_NULL; field->col->mtype = charset == &my_charset_latin1 ? DATA_VARCHAR : DATA_VARMYSQL; - field->col->mbminmaxlen = idx_field->col->mbminmaxlen; - field->col->len = HA_FT_MAXCHARLEN * DATA_MBMAXLEN(field->col->mbminmaxlen); + field->col->mbminlen = idx_field->col->mbminlen; + field->col->mbmaxlen = idx_field->col->mbmaxlen; + field->col->len = HA_FT_MAXCHARLEN * field->col->mbmaxlen; field->fixed_len = 0; @@ -152,7 +153,8 @@ row_merge_create_fts_sort_index( field->col->prtype = DATA_NOT_NULL | DATA_BINARY_TYPE; - field->col->mbminmaxlen = 0; + field->col->mbminlen = 0; + field->col->mbmaxlen = 0; /* The third field is on the word's position in the original doc */ field = dict_index_get_nth_field(new_index, 2); @@ -164,7 +166,8 @@ row_merge_create_fts_sort_index( field->col->len = 4 ; field->fixed_len = 4; field->col->prtype = DATA_NOT_NULL; - field->col->mbminmaxlen = 0; + field->col->mbminlen = 0; + field->col->mbmaxlen = 0; return(new_index); } @@ -658,7 +661,8 @@ row_merge_fts_doc_tokenize( field->type.mtype = DATA_INT; field->type.prtype = DATA_NOT_NULL | DATA_BINARY_TYPE; field->type.len = len; - field->type.mbminmaxlen = 0; + field->type.mbminlen = 0; + field->type.mbmaxlen = 0; cur_len += len; dfield_dup(field, buf->heap); @@ -681,7 +685,8 @@ row_merge_fts_doc_tokenize( field->type.mtype = DATA_INT; field->type.prtype = DATA_NOT_NULL; field->type.len = len; - field->type.mbminmaxlen = 0; + field->type.mbminlen = 0; + field->type.mbmaxlen = 0; cur_len += len; dfield_dup(field, buf->heap); diff --git a/storage/innobase/row/row0import.cc b/storage/innobase/row/row0import.cc index 473e0c25f86..0e7d93d0f32 100644 --- a/storage/innobase/row/row0import.cc +++ b/storage/innobase/row/row0import.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2017, MariaDB Corporation. +Copyright (c) 2015, 2018, MariaDB Corporation. 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 @@ -1202,7 +1202,8 @@ row_import::match_table_columns( err = DB_ERROR; } - if (cfg_col->mbminmaxlen != col->mbminmaxlen) { + if (cfg_col->mbminlen != col->mbminlen + || cfg_col->mbmaxlen != col->mbmaxlen) { ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, @@ -2784,7 +2785,9 @@ row_import_read_columns( col->len = mach_read_from_4(ptr); ptr += sizeof(ib_uint32_t); - col->mbminmaxlen = mach_read_from_4(ptr); + ulint mbminmaxlen = mach_read_from_4(ptr); + col->mbmaxlen = mbminmaxlen / 5; + col->mbminlen = mbminmaxlen % 5; ptr += sizeof(ib_uint32_t); col->ind = mach_read_from_4(ptr); diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index a1b3e428c6e..10e1e7ad06e 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -464,12 +464,9 @@ row_ins_cascade_n_ancestors( /******************************************************************//** Calculates the update vector node->cascade->update for a child table in a cascaded update. -@return number of fields in the calculated update vector; the value -can also be 0 if no foreign key fields changed; the returned value is -ULINT_UNDEFINED if the column type in the child table is too short to -fit the new value in the parent table: that means the update fails */ +@return whether any FULLTEXT INDEX is affected */ static MY_ATTRIBUTE((nonnull, warn_unused_result)) -ulint +bool row_ins_cascade_calc_update_vec( /*============================*/ upd_node_t* node, /*!< in: update node of the parent @@ -478,11 +475,9 @@ row_ins_cascade_calc_update_vec( type is != 0 */ mem_heap_t* heap, /*!< in: memory heap to use as temporary storage */ - trx_t* trx, /*!< in: update transaction */ - ibool* fts_col_affected, - /*!< out: is FTS column affected */ - upd_node_t* cascade) /*!< in: cascade update node */ + trx_t* trx) /*!< in: update transaction */ { + upd_node_t* cascade = node->cascade_node; dict_table_t* table = foreign->foreign_table; dict_index_t* index = foreign->foreign_index; upd_t* update; @@ -493,7 +488,7 @@ row_ins_cascade_calc_update_vec( ulint parent_field_no; ulint i; ulint j; - ibool doc_id_updated = FALSE; + bool doc_id_updated = false; ulint doc_id_pos = 0; doc_id_t new_doc_id = FTS_NULL_DOC_ID; ulint prefix_col; @@ -520,7 +515,7 @@ row_ins_cascade_calc_update_vec( n_fields_updated = 0; - *fts_col_affected = FALSE; + bool affects_fulltext = false; if (table->fts) { doc_id_pos = dict_table_get_nth_col_pos( @@ -572,8 +567,7 @@ row_ins_cascade_calc_update_vec( if (dfield_is_null(&ufield->new_val) && (col->prtype & DATA_NOT_NULL)) { - - return(ULINT_UNDEFINED); + goto err_exit; } /* If the new value would not fit in the @@ -581,15 +575,15 @@ row_ins_cascade_calc_update_vec( if (!dfield_is_null(&ufield->new_val) && dtype_get_at_most_n_mbchars( - col->prtype, col->mbminmaxlen, + col->prtype, + col->mbminlen, col->mbmaxlen, col->len, ufield_len, static_cast<char*>( dfield_get_data( &ufield->new_val))) < ufield_len) { - - return(ULINT_UNDEFINED); + goto err_exit; } /* If the parent column type has a different @@ -633,7 +627,7 @@ row_ins_cascade_calc_update_vec( col->prtype) == DATA_MYSQL_BINARY_CHARSET_COLL) { /* Do not pad BINARY columns */ - return(ULINT_UNDEFINED); + goto err_exit; } row_mysql_pad_col(mbminlen, @@ -650,7 +644,7 @@ row_ins_cascade_calc_update_vec( dict_col_get_no(col), dict_col_is_virtual(col)) != ULINT_UNDEFINED) { - *fts_col_affected = TRUE; + affects_fulltext = true; } /* If Doc ID is updated, check whether the @@ -667,11 +661,14 @@ row_ins_cascade_calc_update_vec( dfield_get_data( &ufield->new_val))); + affects_fulltext = true; + doc_id_updated = true; + if (new_doc_id <= 0) { ib::error() << "FTS Doc ID" " must be larger than" " 0"; - return(ULINT_UNDEFINED); + goto err_exit; } if (new_doc_id < n_doc_id) { @@ -680,12 +677,8 @@ row_ins_cascade_calc_update_vec( << n_doc_id - 1 << " for table " << table->name; - - return(ULINT_UNDEFINED); + goto err_exit; } - - *fts_col_affected = TRUE; - doc_id_updated = TRUE; } n_fields_updated++; @@ -693,8 +686,9 @@ row_ins_cascade_calc_update_vec( } } - /* Generate a new Doc ID if FTS index columns get updated */ - if (table->fts && *fts_col_affected) { + if (affects_fulltext) { + ut_ad(table->fts); + if (DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)) { doc_id_t doc_id; doc_id_t* next_doc_id; @@ -708,24 +702,25 @@ row_ins_cascade_calc_update_vec( fts_get_next_doc_id(table, next_doc_id); doc_id = fts_update_doc_id(table, ufield, next_doc_id); n_fields_updated++; - cascade->fts_next_doc_id = doc_id; + fts_trx_add_op(trx, table, doc_id, FTS_INSERT, NULL); } else { if (doc_id_updated) { ut_ad(new_doc_id); - cascade->fts_next_doc_id = new_doc_id; + fts_trx_add_op(trx, table, new_doc_id, + FTS_INSERT, NULL); } else { - cascade->fts_next_doc_id = FTS_NULL_DOC_ID; ib::error() << "FTS Doc ID must be updated" " along with FTS indexed column for" " table " << table->name; - return(ULINT_UNDEFINED); +err_exit: + n_fields_updated = ULINT_UNDEFINED; } } } update->n_fields = n_fields_updated; - return(n_fields_updated); + return affects_fulltext; } /*********************************************************************//** @@ -1079,13 +1074,10 @@ row_ins_foreign_check_on_constraint( const rec_t* clust_rec; const buf_block_t* clust_block; upd_t* update; - ulint n_to_update; dberr_t err; - ulint i; trx_t* trx; mem_heap_t* tmp_heap = NULL; doc_id_t doc_id = FTS_NULL_DOC_ID; - ibool fts_col_affacted = FALSE; DBUG_ENTER("row_ins_foreign_check_on_constraint"); ut_a(thr); @@ -1129,28 +1121,18 @@ row_ins_foreign_check_on_constraint( DBUG_RETURN(DB_ROW_IS_REFERENCED); } - cascade = row_create_update_node_for_mysql(table, node->cascade_heap); - que_node_set_parent(cascade, node); - - /* For the cascaded operation, all the update nodes are allocated in - the same heap. All the update nodes will point to the same heap. - This heap is owned by the first update node. And it must be freed - only in the first update node */ - cascade->cascade_heap = node->cascade_heap; - cascade->cascade_upd_nodes = node->cascade_upd_nodes; - cascade->new_upd_nodes = node->new_upd_nodes; - cascade->processed_cascades = node->processed_cascades; + if (node->cascade_node == NULL) { + node->cascade_heap = mem_heap_create(128); + node->cascade_node = row_create_update_node_for_mysql( + table, node->cascade_heap); + que_node_set_parent(node->cascade_node, node); + } + cascade = node->cascade_node; cascade->table = table; - cascade->foreign = foreign; - - if (node->is_delete - && (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE)) { - cascade->is_delete = TRUE; - } else { - cascade->is_delete = FALSE; - + if (!(cascade->is_delete = node->is_delete + && (foreign->type & DICT_FOREIGN_ON_DELETE_CASCADE))) { if (foreign->n_fields > cascade->update_n_fields) { /* We have to make the update vector longer */ @@ -1158,31 +1140,32 @@ row_ins_foreign_check_on_constraint( node->cascade_heap); cascade->update_n_fields = foreign->n_fields; } - } - /* We do not allow cyclic cascaded updating (DELETE is allowed, - but not UPDATE) of the same table, as this can lead to an infinite - cycle. Check that we are not updating the same table which is - already being modified in this cascade chain. We have to check - this also because the modification of the indexes of a 'parent' - table may still be incomplete, and we must avoid seeing the indexes - of the parent table in an inconsistent state! */ + /* We do not allow cyclic cascaded updating (DELETE is + allowed, but not UPDATE) of the same table, as this + can lead to an infinite cycle. Check that we are not + updating the same table which is already being + modified in this cascade chain. We have to check this + also because the modification of the indexes of a + 'parent' table may still be incomplete, and we must + avoid seeing the indexes of the parent table in an + inconsistent state! */ - if (!cascade->is_delete - && row_ins_cascade_ancestor_updates_table(cascade, table)) { + if (row_ins_cascade_ancestor_updates_table(cascade, table)) { - /* We do not know if this would break foreign key - constraints, but play safe and return an error */ + /* We do not know if this would break foreign key + constraints, but play safe and return an error */ - err = DB_ROW_IS_REFERENCED; + err = DB_ROW_IS_REFERENCED; - row_ins_foreign_report_err( - "Trying an update, possibly causing a cyclic" - " cascaded update\n" - "in the child table,", thr, foreign, - btr_pcur_get_rec(pcur), entry); + row_ins_foreign_report_err( + "Trying an update, possibly causing a cyclic" + " cascaded update\n" + "in the child table,", thr, foreign, + btr_pcur_get_rec(pcur), entry); - goto nonstandard_exit_func; + goto nonstandard_exit_func; + } } if (row_ins_cascade_n_ancestors(cascade) >= FK_MAX_CASCADE_DEL) { @@ -1287,17 +1270,8 @@ row_ins_foreign_check_on_constraint( if (node->is_delete ? (foreign->type & DICT_FOREIGN_ON_DELETE_SET_NULL) : (foreign->type & DICT_FOREIGN_ON_UPDATE_SET_NULL)) { - /* Build the appropriate update vector which sets foreign->n_fields first fields in rec to SQL NULL */ - if (table->fts) { - - /* For the clause ON DELETE SET NULL, the cascade - operation is actually an update operation with the new - values being null. For FTS, this means that the old - values be deleted and no new values to be added.*/ - cascade->fts_next_doc_id = FTS_NULL_DOC_ID; - } update = cascade->update; @@ -1306,7 +1280,9 @@ row_ins_foreign_check_on_constraint( UNIV_MEM_INVALID(update->fields, update->n_fields * sizeof *update->fields); - for (i = 0; i < foreign->n_fields; i++) { + bool affects_fulltext = false; + + for (ulint i = 0; i < foreign->n_fields; i++) { upd_field_t* ufield = &update->fields[i]; ulint col_no = dict_index_get_nth_col_no( index, i); @@ -1322,18 +1298,19 @@ row_ins_foreign_check_on_constraint( ufield->exp = NULL; dfield_set_null(&ufield->new_val); - if (table->fts && dict_table_is_fts_column( - table->fts->indexes, - dict_index_get_nth_col_no(index, i), - dict_col_is_virtual( - dict_index_get_nth_col(index, i))) + if (!affects_fulltext + && table->fts && dict_table_is_fts_column( + table->fts->indexes, + dict_index_get_nth_col_no(index, i), + dict_col_is_virtual( + dict_index_get_nth_col(index, i))) != ULINT_UNDEFINED) { - fts_col_affacted = TRUE; + affects_fulltext = true; } } - if (fts_col_affacted) { - cascade->fts_doc_id = doc_id; + if (affects_fulltext) { + fts_trx_add_op(trx, table, doc_id, FTS_DELETE, NULL); } if (foreign->v_cols != NULL @@ -1348,19 +1325,22 @@ row_ins_foreign_check_on_constraint( } } else if (table->fts && cascade->is_delete) { /* DICT_FOREIGN_ON_DELETE_CASCADE case */ - for (i = 0; i < foreign->n_fields; i++) { - if (table->fts && dict_table_is_fts_column( + bool affects_fulltext = false; + + for (ulint i = 0; i < foreign->n_fields; i++) { + if (dict_table_is_fts_column( table->fts->indexes, dict_index_get_nth_col_no(index, i), dict_col_is_virtual( dict_index_get_nth_col(index, i))) != ULINT_UNDEFINED) { - fts_col_affacted = TRUE; + affects_fulltext = true; + break; } } - if (fts_col_affacted) { - cascade->fts_doc_id = doc_id; + if (affects_fulltext) { + fts_trx_add_op(trx, table, doc_id, FTS_DELETE, NULL); } } @@ -1370,13 +1350,10 @@ row_ins_foreign_check_on_constraint( /* Build the appropriate update vector which sets changing foreign->n_fields first fields in rec to new values */ - n_to_update = row_ins_cascade_calc_update_vec( - node, foreign, cascade->cascade_heap, - trx, &fts_col_affacted, cascade); + bool affects_fulltext = row_ins_cascade_calc_update_vec( + node, foreign, tmp_heap, trx); - - if (foreign->v_cols != NULL - && foreign->v_cols->size() > 0) { + if (foreign->v_cols && !foreign->v_cols->empty()) { row_ins_foreign_fill_virtual( cascade, clust_rec, clust_index, node, foreign, &err); @@ -1386,7 +1363,8 @@ row_ins_foreign_check_on_constraint( } } - if (n_to_update == ULINT_UNDEFINED) { + switch (cascade->update->n_fields) { + case ULINT_UNDEFINED: err = DB_ROW_IS_REFERENCED; row_ins_foreign_report_err( @@ -1399,10 +1377,7 @@ row_ins_foreign_check_on_constraint( thr, foreign, btr_pcur_get_rec(pcur), entry); goto nonstandard_exit_func; - } - - if (cascade->update->n_fields == 0) { - + case 0: /* The update does not change any columns referred to in this foreign key constraint: no need to do anything */ @@ -1413,9 +1388,9 @@ row_ins_foreign_check_on_constraint( } /* Mark the old Doc ID as deleted */ - if (fts_col_affacted) { + if (affects_fulltext) { ut_ad(table->fts); - cascade->fts_doc_id = doc_id; + fts_trx_add_op(trx, table, doc_id, FTS_DELETE, NULL); } } @@ -1437,22 +1412,15 @@ row_ins_foreign_check_on_constraint( cascade->state = UPD_NODE_UPDATE_CLUSTERED; #ifdef WITH_WSREP - err = wsrep_append_foreign_key( - thr_get_trx(thr), - foreign, - clust_rec, - clust_index, + err = wsrep_append_foreign_key(trx, foreign, clust_rec, clust_index, FALSE, FALSE); if (err != DB_SUCCESS) { fprintf(stderr, "WSREP: foreign key append failed: %d\n", err); } else #endif /* WITH_WSREP */ - node->new_upd_nodes->push_back(cascade); - - my_atomic_addlint(&table->n_foreign_key_checks_running, 1); - - ut_ad(foreign->foreign_table->n_foreign_key_checks_running > 0); + err = row_update_cascade_for_mysql(thr, cascade, + foreign->foreign_table); /* Release the data dictionary latch for a while, so that we do not starve other threads from doing CREATE TABLE etc. if we have a huge @@ -1479,7 +1447,6 @@ row_ins_foreign_check_on_constraint( DBUG_RETURN(err); nonstandard_exit_func: - que_graph_free_recursive(cascade); if (tmp_heap) { mem_heap_free(tmp_heap); @@ -1557,17 +1524,6 @@ row_ins_set_exclusive_rec_lock( return(err); } -/* Decrement a counter in the destructor. */ -class ib_dec_in_dtor { -public: - ib_dec_in_dtor(ulint& c): counter(c) {} - ~ib_dec_in_dtor() { - my_atomic_addlint(&counter, -1); - } -private: - ulint& counter; -}; - /***************************************************************//** Checks if foreign key constraint fails for an index entry. Sets shared locks which lock either the success or the failure of the constraint. NOTE that @@ -1892,10 +1848,6 @@ end_scan: do_possible_lock_wait: if (err == DB_LOCK_WAIT) { - /* An object that will correctly decrement the FK check counter - when it goes out of this scope. */ - ib_dec_in_dtor dec(check_table->n_foreign_key_checks_running); - trx->error_state = err; que_thr_stop_for_mysql(thr); @@ -1912,9 +1864,13 @@ do_possible_lock_wait: thr->lock_state = QUE_THR_LOCK_NOLOCK; - err = check_table->to_be_dropped - ? DB_LOCK_WAIT_TIMEOUT - : trx->error_state; + if (check_table->to_be_dropped + || trx->error_state == DB_LOCK_WAIT_TIMEOUT) { + err = DB_LOCK_WAIT_TIMEOUT; + } + + my_atomic_addlint(&check_table->n_foreign_key_checks_running, + -1); } exit_func: @@ -1975,6 +1931,12 @@ row_ins_check_foreign_constraints( row_mysql_freeze_data_dictionary(trx); } + if (referenced_table) { + my_atomic_addlint( + &foreign->foreign_table + ->n_foreign_key_checks_running, 1); + } + /* NOTE that if the thread ends up waiting for a lock we will release dict_operation_lock temporarily! But the counter on the table protects the referenced @@ -1983,6 +1945,12 @@ row_ins_check_foreign_constraints( err = row_ins_check_foreign_constraint( TRUE, foreign, table, entry, thr); + if (referenced_table) { + my_atomic_addlint( + &foreign->foreign_table + ->n_foreign_key_checks_running, -1); + } + if (got_s_lock) { row_mysql_unfreeze_data_dictionary(trx); } @@ -2859,21 +2827,18 @@ row_ins_sec_index_entry_low( cursor.rtr_info = NULL; ut_ad(thr_get_trx(thr)->id != 0); - mtr_start(&mtr); - mtr.set_named_space(index->space); - - if (dict_table_is_temporary(index->table)) { - /* Disable REDO logging as the lifetime of temp-tables is - limited to server or connection lifetime and so REDO - information is not needed on restart for recovery. - Disable locking as temp-tables are local to a connection. */ + mtr.start(); + if (index->table->is_temporary()) { + /* Disable locking, because temporary tables are never + shared between transactions or connections. */ ut_ad(flags & BTR_NO_LOCKING_FLAG); mtr.set_log_mode(MTR_LOG_NO_REDO); - } else if (!dict_index_is_spatial(index)) { - /* Enable insert buffering if it's neither temp-table - nor spatial index. */ - search_mode |= BTR_INSERT; + } else { + mtr.set_named_space(index->space); + if (!dict_index_is_spatial(index)) { + search_mode |= BTR_INSERT; + } } /* Ensure that we acquire index->lock when inserting into an @@ -2945,10 +2910,8 @@ row_ins_sec_index_entry_low( } if (err != DB_SUCCESS) { - trx_t* trx = thr_get_trx(thr); - if (err == DB_DECRYPTION_FAILED) { - ib_push_warning(trx->mysql_thd, + ib_push_warning(thr_get_trx(thr)->mysql_thd, DB_DECRYPTION_FAILED, "Table %s is encrypted but encryption service or" " used key_id is not available. " @@ -3424,7 +3387,7 @@ row_ins_index_entry_set_vals( = dict_field_get_col(ind_field); len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminmaxlen, + col->prtype, col->mbminlen, col->mbmaxlen, ind_field->prefix_len, len, static_cast<const char*>( diff --git a/storage/innobase/row/row0log.cc b/storage/innobase/row/row0log.cc index 4dfc25e7779..90f219dce6a 100644 --- a/storage/innobase/row/row0log.cc +++ b/storage/innobase/row/row0log.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -1201,7 +1201,7 @@ row_log_table_get_pk( dict_field_t* ifield; dfield_t* dfield; ulint prtype; - ulint mbminmaxlen; + ulint mbminlen, mbmaxlen; ifield = dict_index_get_nth_field(new_index, new_i); dfield = dtuple_get_nth_field(tuple, new_i); @@ -1230,7 +1230,8 @@ err_exit: goto func_exit; } - mbminmaxlen = col->mbminmaxlen; + mbminlen = col->mbminlen; + mbmaxlen = col->mbmaxlen; prtype = col->prtype; } else { /* No matching column was found in the old @@ -1240,7 +1241,8 @@ err_exit: dfield_copy(dfield, dtuple_get_nth_field( log->add_cols, col_no)); - mbminmaxlen = dfield->type.mbminmaxlen; + mbminlen = dfield->type.mbminlen; + mbmaxlen = dfield->type.mbmaxlen; prtype = dfield->type.prtype; } @@ -1249,7 +1251,7 @@ err_exit: if (ifield->prefix_len) { ulint len = dtype_get_at_most_n_mbchars( - prtype, mbminmaxlen, + prtype, mbminlen, mbmaxlen, ifield->prefix_len, dfield_get_len(dfield), static_cast<const char*>( diff --git a/storage/innobase/row/row0merge.cc b/storage/innobase/row/row0merge.cc index 4776bcc3c25..c50e8fbd6ae 100644 --- a/storage/innobase/row/row0merge.cc +++ b/storage/innobase/row/row0merge.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2017, MariaDB Corporation. +Copyright (c) 2014, 2018, MariaDB Corporation. 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 @@ -452,8 +452,8 @@ row_merge_buf_redundant_convert( const page_size_t& page_size, mem_heap_t* heap) { - ut_ad(DATA_MBMINLEN(field->type.mbminmaxlen) == 1); - ut_ad(DATA_MBMAXLEN(field->type.mbminmaxlen) > 1); + ut_ad(field->type.mbminlen == 1); + ut_ad(field->type.mbmaxlen > 1); byte* buf = (byte*) mem_heap_alloc(heap, len); ulint field_len = row_field->len; @@ -595,7 +595,8 @@ row_merge_buf_add( field->type.mtype = ifield->col->mtype; field->type.prtype = ifield->col->prtype; - field->type.mbminmaxlen = DATA_MBMINMAXLEN(0, 0); + field->type.mbminlen = 0; + field->type.mbmaxlen = 0; field->type.len = ifield->col->len; } else { /* Use callback to get the virtual column value */ @@ -746,7 +747,7 @@ row_merge_buf_add( if (ifield->prefix_len) { len = dtype_get_at_most_n_mbchars( col->prtype, - col->mbminmaxlen, + col->mbminlen, col->mbmaxlen, ifield->prefix_len, len, static_cast<char*>(dfield_get_data(field))); @@ -758,8 +759,7 @@ row_merge_buf_add( fixed_len = ifield->fixed_len; if (fixed_len && !dict_table_is_comp(index->table) - && DATA_MBMINLEN(col->mbminmaxlen) - != DATA_MBMAXLEN(col->mbminmaxlen)) { + && col->mbminlen != col->mbmaxlen) { /* CHAR in ROW_FORMAT=REDUNDANT is always fixed-length, but in the temporary file it is variable-length for variable-length character @@ -769,14 +769,11 @@ row_merge_buf_add( if (fixed_len) { #ifdef UNIV_DEBUG - ulint mbminlen = DATA_MBMINLEN(col->mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN(col->mbminmaxlen); - /* len should be between size calcualted base on mbmaxlen and mbminlen */ ut_ad(len <= fixed_len); - ut_ad(!mbmaxlen || len >= mbminlen - * (fixed_len / mbmaxlen)); + ut_ad(!col->mbmaxlen || len >= col->mbminlen + * (fixed_len / col->mbmaxlen)); ut_ad(!dfield_is_ext(field)); #endif /* UNIV_DEBUG */ @@ -4596,6 +4593,8 @@ row_merge_build_indexes( DBUG_RETURN(DB_OUT_OF_MEMORY); } + TRASH_ALLOC(&crypt_pfx, sizeof crypt_pfx); + if (log_tmp_is_encrypted()) { crypt_block = static_cast<row_merge_block_t*>( alloc.allocate_large(3 * srv_sort_buf_size, diff --git a/storage/innobase/row/row0mysql.cc b/storage/innobase/row/row0mysql.cc index bff52ad7db6..0aa738fa6c8 100644 --- a/storage/innobase/row/row0mysql.cc +++ b/storage/innobase/row/row0mysql.cc @@ -307,29 +307,6 @@ row_mysql_store_geometry( mach_write_to_n_little_endian(dest, dest_len - 8, src_len); memcpy(dest + dest_len - 8, &src, sizeof src); - - DBUG_EXECUTE_IF("row_print_geometry_data", - { - String res; - Geometry_buffer buffer; - String wkt; - - /** Show the meaning of geometry data. */ - Geometry* g = Geometry::construct( - &buffer, (const char*)src, (uint32) src_len); - - if (g) - { - /* - if (g->as_wkt(&wkt) == 0) - { - ib::info() << "Write geometry data to" - " MySQL WKT format: " - << wkt.c_ptr_safe() << "."; - } - */ - } - }); } /*******************************************************************//** @@ -350,29 +327,6 @@ row_mysql_read_geometry( memcpy(&data, ref + col_len - 8, sizeof data); - DBUG_EXECUTE_IF("row_print_geometry_data", - { - String res; - Geometry_buffer buffer; - String wkt; - - /** Show the meaning of geometry data. */ - Geometry* g = Geometry::construct( - &buffer, (const char*) data, (uint32) *len); - - if (g) - { - /* - if (g->as_wkt(&wkt) == 0) - { - ib::info() << "Read geometry data in" - " MySQL's WKT format: " - << wkt.c_ptr_safe() << "."; - } - */ - } - }); - return(data); } @@ -1647,8 +1601,6 @@ row_create_update_node_for_mysql( node->table_sym = NULL; node->col_assign_list = NULL; - node->fts_doc_id = FTS_NULL_DOC_ID; - node->fts_next_doc_id = UINT64_UNDEFINED; DBUG_RETURN(node); } @@ -1696,9 +1648,9 @@ row_fts_do_update( doc_id_t old_doc_id, /* in: old document id */ doc_id_t new_doc_id) /* in: new document id */ { - fts_trx_add_op(trx, table, old_doc_id, FTS_DELETE, NULL); - - if (new_doc_id != FTS_NULL_DOC_ID) { + if(trx->fts_next_doc_id) { + fts_trx_add_op(trx, table, old_doc_id, FTS_DELETE, NULL); + if(new_doc_id != FTS_NULL_DOC_ID) fts_trx_add_op(trx, table, new_doc_id, FTS_INSERT, NULL); } } @@ -1710,24 +1662,30 @@ static dberr_t row_fts_update_or_delete( /*=====================*/ - trx_t* trx, - upd_node_t* node) /* in: prebuilt struct in MySQL + row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL handle */ { - dict_table_t* table = node->table; - doc_id_t old_doc_id = node->fts_doc_id; + trx_t* trx = prebuilt->trx; + dict_table_t* table = prebuilt->table; + upd_node_t* node = prebuilt->upd_node; + doc_id_t old_doc_id = prebuilt->fts_doc_id; + DBUG_ENTER("row_fts_update_or_delete"); - ut_a(dict_table_has_fts_index(node->table)); + ut_a(dict_table_has_fts_index(prebuilt->table)); /* Deletes are simple; get them out of the way first. */ if (node->is_delete) { /* A delete affects all FTS indexes, so we pass NULL */ fts_trx_add_op(trx, table, old_doc_id, FTS_DELETE, NULL); } else { - doc_id_t new_doc_id = node->fts_next_doc_id; - ut_ad(new_doc_id != UINT64_UNDEFINED); + doc_id_t new_doc_id; + new_doc_id = fts_read_doc_id((byte*) &trx->fts_next_doc_id); + if (new_doc_id == 0) { + ib::error() << "InnoDB FTS: Doc ID cannot be 0"; + return(DB_FTS_INVALID_DOCID); + } row_fts_do_update(trx, table, old_doc_id, new_doc_id); } @@ -1776,19 +1734,6 @@ init_fts_doc_id_for_ref( } } -/* A functor for decrementing counters. */ -class ib_dec_counter { -public: - ib_dec_counter() {} - - void operator() (upd_node_t* node) { - ut_ad(node->table->n_foreign_key_checks_running > 0); - my_atomic_addlint( - &node->table->n_foreign_key_checks_running, -1); - } -}; - - /** Does an update or delete of a row for MySQL. @param[in,out] prebuilt prebuilt struct in MySQL handle @return error code or DB_SUCCESS */ @@ -1798,15 +1743,11 @@ row_update_for_mysql(row_prebuilt_t* prebuilt) trx_savept_t savept; dberr_t err; que_thr_t* thr; - ibool was_lock_wait; dict_index_t* clust_index; upd_node_t* node; dict_table_t* table = prebuilt->table; trx_t* trx = prebuilt->trx; ulint fk_depth = 0; - upd_cascade_t* cascade_upd_nodes; - upd_cascade_t* new_upd_nodes; - upd_cascade_t* processed_cascades; bool got_s_lock = false; DBUG_ENTER("row_update_for_mysql"); @@ -1853,26 +1794,6 @@ row_update_for_mysql(row_prebuilt_t* prebuilt) const bool is_delete = node->is_delete; ut_ad(node->table == table); - if (node->cascade_heap) { - mem_heap_empty(node->cascade_heap); - } else { - node->cascade_heap = mem_heap_create(128); - } - - mem_heap_allocator<upd_node_t*> mem_heap_ator(node->cascade_heap); - - cascade_upd_nodes = new - (mem_heap_ator.allocate(sizeof(upd_cascade_t))) - upd_cascade_t(deque_mem_heap_t(mem_heap_ator)); - - new_upd_nodes = new - (mem_heap_ator.allocate(sizeof(upd_cascade_t))) - upd_cascade_t(deque_mem_heap_t(mem_heap_ator)); - - processed_cascades = new - (mem_heap_ator.allocate(sizeof(upd_cascade_t))) - upd_cascade_t(deque_mem_heap_t(mem_heap_ator)); - clust_index = dict_table_get_first_index(table); if (prebuilt->pcur->btr_cur.index == clust_index) { @@ -1897,121 +1818,52 @@ row_update_for_mysql(row_prebuilt_t* prebuilt) node->state = UPD_NODE_UPDATE_CLUSTERED; - node->cascade_top = true; - node->cascade_upd_nodes = cascade_upd_nodes; - node->new_upd_nodes = new_upd_nodes; - node->processed_cascades = processed_cascades; - node->fts_doc_id = prebuilt->fts_doc_id; - - if (trx->fts_next_doc_id != UINT64_UNDEFINED) { - node->fts_next_doc_id = fts_read_doc_id( - (byte*) &trx->fts_next_doc_id); - } else { - node->fts_next_doc_id = UINT64_UNDEFINED; - } - ut_ad(!prebuilt->sql_stat_start); que_thr_move_to_run_state_for_mysql(thr, trx); - thr->fk_cascade_depth = 0; - -run_again: - if (thr->fk_cascade_depth == 1 && trx->dict_operation_lock_mode == 0) { - got_s_lock = true; - row_mysql_freeze_data_dictionary(trx); - } - - thr->run_node = node; - thr->prev_node = node; - - row_upd_step(thr); + for (;;) { + thr->run_node = node; + thr->prev_node = node; + thr->fk_cascade_depth = 0; - DBUG_EXECUTE_IF("dml_cascade_only_once", node->check_cascade_only_once();); + row_upd_step(thr); - err = trx->error_state; + err = trx->error_state; - if (err != DB_SUCCESS) { + if (err == DB_SUCCESS) { + break; + } que_thr_stop_for_mysql(thr); if (err == DB_RECORD_NOT_FOUND) { trx->error_state = DB_SUCCESS; - trx->op_info = ""; - - if (thr->fk_cascade_depth > 0) { - que_graph_free_recursive(node); - } goto error; } - /* Since reporting a plain "duplicate key" error message to - the user in cases where a long CASCADE operation would lead - to a duplicate key in some other table is very confusing, - map duplicate key errors resulting from FK constraints to a - separate error code. */ - if (err == DB_DUPLICATE_KEY && thr->fk_cascade_depth > 0) { - err = DB_FOREIGN_DUPLICATE_KEY; - trx->error_state = err; - } - thr->lock_state= QUE_THR_LOCK_ROW; DEBUG_SYNC(trx->mysql_thd, "row_update_for_mysql_error"); - was_lock_wait = row_mysql_handle_errors(&err, trx, thr, - &savept); + bool was_lock_wait = row_mysql_handle_errors( + &err, trx, thr, &savept); thr->lock_state= QUE_THR_LOCK_NOLOCK; - if (was_lock_wait) { - std::for_each(new_upd_nodes->begin(), - new_upd_nodes->end(), - ib_dec_counter()); - std::for_each(new_upd_nodes->begin(), - new_upd_nodes->end(), - que_graph_free_recursive); - node->new_upd_nodes->clear(); - goto run_again; - } - - trx->op_info = ""; - - if (thr->fk_cascade_depth > 0) { - que_graph_free_recursive(node); + if (!was_lock_wait) { + goto error; } - goto error; - } else { - - std::copy(node->new_upd_nodes->begin(), - node->new_upd_nodes->end(), - std::back_inserter(*node->cascade_upd_nodes)); - - node->new_upd_nodes->clear(); - } - - if (dict_table_has_fts_index(node->table) - && node->fts_doc_id != FTS_NULL_DOC_ID - && node->fts_next_doc_id != UINT64_UNDEFINED) { - err = row_fts_update_or_delete(trx, node); - ut_a(err == DB_SUCCESS); } - if (thr->fk_cascade_depth > 0) { - /* Processing cascade operation */ - ut_ad(node->table->n_foreign_key_checks_running > 0); - my_atomic_addlint( - &node->table->n_foreign_key_checks_running, -1); - node->processed_cascades->push_back(node); - } - - if (!cascade_upd_nodes->empty()) { - DEBUG_SYNC_C("foreign_constraint_update_cascade"); - node = cascade_upd_nodes->front(); - node->cascade_upd_nodes = cascade_upd_nodes; - cascade_upd_nodes->pop_front(); - thr->fk_cascade_depth++; + que_thr_stop_for_mysql_no_error(thr, trx); - goto run_again; + if (dict_table_has_fts_index(table) + && trx->fts_next_doc_id != UINT64_UNDEFINED) { + err = row_fts_update_or_delete(prebuilt); + if (UNIV_UNLIKELY(err != DB_SUCCESS)) { + ut_ad(!"unexpected error"); + goto error; + } } /* Completed cascading operations (if any) */ @@ -2019,45 +1871,10 @@ run_again: row_mysql_unfreeze_data_dictionary(trx); } - thr->fk_cascade_depth = 0; - - /* Update the statistics of each involved table - only after completing all operations, including - FOREIGN KEY...ON...CASCADE|SET NULL. */ bool update_statistics; + ut_ad(node->is_delete == is_delete); - for (upd_cascade_t::iterator i = processed_cascades->begin(); - i != processed_cascades->end(); - ++i) { - - node = *i; - - if (node->is_delete) { - /* Not protected by dict_table_stats_lock() for - performance reasons, we would rather get garbage - in stat_n_rows (which is just an estimate anyway) - than protecting the following code with a latch. */ - dict_table_n_rows_dec(node->table); - - update_statistics = !srv_stats_include_delete_marked; - srv_stats.n_rows_deleted.inc(size_t(trx->id)); - } else { - update_statistics - = !(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE); - srv_stats.n_rows_updated.inc(size_t(trx->id)); - } - - if (update_statistics) { - dict_stats_update_if_needed(node->table); - } else { - /* Always update the table modification counter. */ - node->table->stat_modified_counter++; - } - - que_graph_free_recursive(node); - } - - if (is_delete) { + if (/*node->*/is_delete) { /* Not protected by dict_table_stats_lock() for performance reasons, we would rather get garbage in stat_n_rows (which is just an estimate anyway) than protecting the following code @@ -2091,45 +1908,14 @@ run_again: trx->op_info = ""; - que_thr_stop_for_mysql_no_error(thr, trx); - - DBUG_ASSERT(cascade_upd_nodes->empty()); - DBUG_RETURN(err); error: + trx->op_info = ""; if (got_s_lock) { row_mysql_unfreeze_data_dictionary(trx); } - if (thr->fk_cascade_depth > 0) { - ut_ad(node->table->n_foreign_key_checks_running > 0); - my_atomic_addlint( - &node->table->n_foreign_key_checks_running, -1); - thr->fk_cascade_depth = 0; - } - - /* Reset the table->n_foreign_key_checks_running counter */ - std::for_each(cascade_upd_nodes->begin(), - cascade_upd_nodes->end(), - ib_dec_counter()); - - std::for_each(new_upd_nodes->begin(), - new_upd_nodes->end(), - ib_dec_counter()); - - std::for_each(cascade_upd_nodes->begin(), - cascade_upd_nodes->end(), - que_graph_free_recursive); - - std::for_each(new_upd_nodes->begin(), - new_upd_nodes->end(), - que_graph_free_recursive); - - std::for_each(processed_cascades->begin(), - processed_cascades->end(), - que_graph_free_recursive); - DBUG_RETURN(err); } @@ -2296,6 +2082,89 @@ row_mysql_unfreeze_data_dictionary( trx->dict_operation_lock_mode = 0; } +/**********************************************************************//** +Does a cascaded delete or set null in a foreign key operation. +@return error code or DB_SUCCESS */ +dberr_t +row_update_cascade_for_mysql( +/*=========================*/ + que_thr_t* thr, /*!< in: query thread */ + upd_node_t* node, /*!< in: update node used in the cascade + or set null operation */ + dict_table_t* table) /*!< in: table where we do the operation */ +{ + /* Increment fk_cascade_depth to record the recursive call depth on + a single update/delete that affects multiple tables chained + together with foreign key relations. */ + + if (++thr->fk_cascade_depth > FK_MAX_CASCADE_DEL) { + return(DB_FOREIGN_EXCEED_MAX_CASCADE); + } + + const trx_t* trx = thr_get_trx(thr); + + for (;;) { + thr->run_node = node; + thr->prev_node = node; + + DEBUG_SYNC_C("foreign_constraint_update_cascade"); + { + TABLE *mysql_table = thr->prebuilt->m_mysql_table; + thr->prebuilt->m_mysql_table = NULL; + row_upd_step(thr); + thr->prebuilt->m_mysql_table = mysql_table; + } + + switch (trx->error_state) { + case DB_LOCK_WAIT: + que_thr_stop_for_mysql(thr); + lock_wait_suspend_thread(thr); + + if (trx->error_state == DB_SUCCESS) { + continue; + } + + /* fall through */ + default: + /* Other errors are handled for the parent node. */ + thr->fk_cascade_depth = 0; + return trx->error_state; + + case DB_SUCCESS: + thr->fk_cascade_depth = 0; + bool stats; + + if (node->is_delete) { + /* Not protected by + dict_table_stats_lock() for + performance reasons, we would rather + get garbage in stat_n_rows (which is + just an estimate anyway) than + protecting the following code with a + latch. */ + dict_table_n_rows_dec(node->table); + + stats = !srv_stats_include_delete_marked; + srv_stats.n_rows_deleted.inc(size_t(trx->id)); + } else { + stats = !(node->cmpl_info + & UPD_NODE_NO_ORD_CHANGE); + srv_stats.n_rows_updated.inc(size_t(trx->id)); + } + + if (stats) { + dict_stats_update_if_needed(node->table); + } else { + /* Always update the table + modification counter. */ + node->table->stat_modified_counter++; + } + + return(DB_SUCCESS); + } + } +} + /*********************************************************************//** Locks the data dictionary exclusively for performing a table create or other data dictionary modification operation. */ @@ -4898,59 +4767,6 @@ funct_exit: return(err); } -/** Renames a partitioned table for MySQL. -@param[in] old_name Old table name. -@param[in] new_name New table name. -@param[in,out] trx Transaction. -@return error code or DB_SUCCESS */ -dberr_t -row_rename_partitions_for_mysql( - const char* old_name, - const char* new_name, - trx_t* trx) -{ - char from_name[FN_REFLEN]; - char to_name[FN_REFLEN]; - ulint from_len = strlen(old_name); - ulint to_len = strlen(new_name); - char* table_name; - dberr_t error = DB_TABLE_NOT_FOUND; - - ut_a(from_len < (FN_REFLEN - 4)); - ut_a(to_len < (FN_REFLEN - 4)); - memcpy(from_name, old_name, from_len); - from_name[from_len] = '#'; - from_name[from_len + 1] = 0; - while ((table_name = dict_get_first_table_name_in_db(from_name))) { - ut_a(memcmp(table_name, from_name, from_len) == 0); - /* Must match #[Pp]#<partition_name> */ - if (strlen(table_name) <= (from_len + 3) - || table_name[from_len] != '#' - || table_name[from_len + 2] != '#' - || (table_name[from_len + 1] != 'P' - && table_name[from_len + 1] != 'p')) { - - ut_ad(0); - ut_free(table_name); - continue; - } - memcpy(to_name, new_name, to_len); - memcpy(to_name + to_len, table_name + from_len, - strlen(table_name) - from_len + 1); - error = row_rename_table_for_mysql(table_name, to_name, - trx, false); - if (error != DB_SUCCESS) { - /* Rollback and return. */ - trx_rollback_for_mysql(trx); - ut_free(table_name); - return(error); - } - ut_free(table_name); - } - trx_commit_for_mysql(trx); - return(error); -} - /*********************************************************************//** Scans an index for either COUNT(*) or CHECK TABLE. If CHECK TABLE; Checks that the index contains entries in an ascending order, diff --git a/storage/innobase/row/row0quiesce.cc b/storage/innobase/row/row0quiesce.cc index 77cb35b8f21..938f9156717 100644 --- a/storage/innobase/row/row0quiesce.cc +++ b/storage/innobase/row/row0quiesce.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -239,7 +239,11 @@ row_quiesce_write_table( mach_write_to_4(ptr, col->len); ptr += sizeof(ib_uint32_t); - mach_write_to_4(ptr, col->mbminmaxlen); + /* FIXME: This will not work if mbminlen>4. + This field is also redundant, because the lengths + are a property of the character set encoding, which + in turn is encodedin prtype above. */ + mach_write_to_4(ptr, col->mbmaxlen * 5 + col->mbminlen); ptr += sizeof(ib_uint32_t); mach_write_to_4(ptr, col->ind); diff --git a/storage/innobase/row/row0row.cc b/storage/innobase/row/row0row.cc index f6fb96e1ce1..ad4991fb4e9 100644 --- a/storage/innobase/row/row0row.cc +++ b/storage/innobase/row/row0row.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, MariaDB Corporation. 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 @@ -334,7 +335,7 @@ row_build_index_entry_low( /* If a column prefix index, take only the prefix. */ if (ind_field->prefix_len) { len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminmaxlen, + col->prtype, col->mbminlen, col->mbmaxlen, ind_field->prefix_len, len, static_cast<char*>(dfield_get_data(dfield))); dfield_set_len(dfield, len); @@ -846,7 +847,8 @@ row_build_row_ref( dfield_set_len(dfield, dtype_get_at_most_n_mbchars( dtype->prtype, - dtype->mbminmaxlen, + dtype->mbminlen, + dtype->mbmaxlen, clust_col_prefix_len, len, (char*) field)); } @@ -946,7 +948,8 @@ row_build_row_ref_in_tuple( dfield_set_len(dfield, dtype_get_at_most_n_mbchars( dtype->prtype, - dtype->mbminmaxlen, + dtype->mbminlen, + dtype->mbmaxlen, clust_col_prefix_len, len, (char*) field)); } diff --git a/storage/innobase/row/row0sel.cc b/storage/innobase/row/row0sel.cc index 507ed9020e9..157c2ab64da 100644 --- a/storage/innobase/row/row0sel.cc +++ b/storage/innobase/row/row0sel.cc @@ -2,7 +2,7 @@ Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. -Copyright (c) 2015, 2017, MariaDB Corporation. +Copyright (c) 2015, 2018, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -88,8 +88,10 @@ row_sel_sec_rec_is_for_blob( /*========================*/ ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of - a multi-byte character */ + ulint mbminlen, /*!< in: minimum length of + a character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of + a character, in bytes */ const byte* clust_field, /*!< in: the locally stored part of the clustered index column, including the BLOB pointer; the clustered @@ -137,7 +139,7 @@ row_sel_sec_rec_is_for_blob( return(FALSE); } - len = dtype_get_at_most_n_mbchars(prtype, mbminmaxlen, + len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen, prefix_len, len, (const char*) buf); return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len)); @@ -259,14 +261,14 @@ row_sel_sec_rec_is_for_clust_rec( } len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminmaxlen, + col->prtype, col->mbminlen, col->mbmaxlen, ifield->prefix_len, len, (char*) clust_field); if (rec_offs_nth_extern(clust_offs, clust_pos) && len < sec_len) { if (!row_sel_sec_rec_is_for_blob( col->mtype, col->prtype, - col->mbminmaxlen, + col->mbminlen, col->mbmaxlen, clust_field, clust_len, sec_field, sec_len, ifield->prefix_len, @@ -517,7 +519,6 @@ row_sel_fetch_columns( rec, offsets, dict_table_page_size(index->table), field_no, &len, heap); - //field_no, &len, heap, NULL); /* data == NULL means that the externally stored field was not @@ -1029,7 +1030,7 @@ row_sel_get_clust_rec( /* Fetch the columns needed in test conditions. The clustered index record is protected by a page latch that was acquired when plan->clust_pcur was positioned. The latch will not be - released until mtr_commit(mtr). */ + released until mtr->commit(). */ ut_ad(!rec_get_deleted_flag(clust_rec, rec_offs_comp(offsets))); row_sel_fetch_columns(index, clust_rec, offsets, @@ -1096,14 +1097,14 @@ retry: if (err == DB_LOCK_WAIT) { re_scan: - mtr_commit(mtr); + mtr->commit(); trx->error_state = err; que_thr_stop_for_mysql(thr); thr->lock_state = QUE_THR_LOCK_ROW; if (row_mysql_handle_errors( &err, trx, thr, NULL)) { thr->lock_state = QUE_THR_LOCK_NOLOCK; - mtr_start(mtr); + mtr->start(); mutex_enter(&match->rtr_match_mutex); if (!match->valid && match->matched_recs->empty()) { @@ -1123,7 +1124,7 @@ re_scan: RW_X_LATCH, NULL, BUF_GET, __FILE__, __LINE__, mtr, &err); } else { - mtr_start(mtr); + mtr->start(); goto func_end; } @@ -1131,8 +1132,8 @@ re_scan: if (!match->valid) { /* Page got deleted */ - mtr_commit(mtr); - mtr_start(mtr); + mtr->commit(); + mtr->start(); err = DB_RECORD_NOT_FOUND; goto func_end; } @@ -1150,8 +1151,8 @@ re_scan: /* Page got splitted and promoted (only for root page it is possible). Release the page and ask for a re-search */ - mtr_commit(mtr); - mtr_start(mtr); + mtr->commit(); + mtr->start(); err = DB_RECORD_NOT_FOUND; goto func_end; } @@ -1163,8 +1164,8 @@ re_scan: /* No match record */ if (page_rec_is_supremum(rec) || !match->valid) { - mtr_commit(mtr); - mtr_start(mtr); + mtr->commit(); + mtr->start(); err = DB_RECORD_NOT_FOUND; goto func_end; } @@ -1536,7 +1537,7 @@ row_sel_try_search_shortcut( /* Fetch the columns needed in test conditions. The index record is protected by a page latch that was acquired when plan->pcur was positioned. The latch will not be released - until mtr_commit(mtr). */ + until mtr->commit(). */ row_sel_fetch_columns(index, rec, offsets, UT_LIST_GET_FIRST(plan->columns)); @@ -1653,7 +1654,7 @@ table_loop: /* Open a cursor to index, or restore an open cursor position */ - mtr_start(&mtr); + mtr.start(); #ifdef BTR_CUR_HASH_ADAPT if (consistent_read && plan->unique_search && !plan->pcur_is_open @@ -1691,8 +1692,8 @@ table_loop: plan_reset_cursor(plan); - mtr_commit(&mtr); - mtr_start(&mtr); + mtr.commit(); + mtr.start(); } if (search_latch_locked) { @@ -1953,7 +1954,7 @@ skip_lock: by row_sel_open_pcur() or row_sel_restore_pcur_pos(). The latch will not be released - until mtr_commit(mtr). */ + until mtr.commit(). */ row_sel_fetch_columns( index, rec, offsets, @@ -1983,7 +1984,7 @@ skip_lock: /* Fetch the columns needed in test conditions. The record is protected by a page latch that was acquired by row_sel_open_pcur() or row_sel_restore_pcur_pos(). The latch - will not be released until mtr_commit(mtr). */ + will not be released until mtr.commit(). */ row_sel_fetch_columns(index, rec, offsets, UT_LIST_GET_FIRST(plan->columns)); @@ -2149,7 +2150,7 @@ next_table: btr_pcur_store_position(&(plan->pcur), &mtr); } - mtr_commit(&mtr); + mtr.commit(); mtr_has_extra_clust_latch = FALSE; @@ -2189,7 +2190,7 @@ table_exhausted: plan->cursor_at_end = TRUE; - mtr_commit(&mtr); + mtr.commit(); mtr_has_extra_clust_latch = FALSE; @@ -2239,7 +2240,7 @@ stop_for_a_while: plan->stored_cursor_rec_processed = FALSE; btr_pcur_store_position(&(plan->pcur), &mtr); - mtr_commit(&mtr); + mtr.commit(); ut_ad(!sync_check_iterate(sync_check())); err = DB_SUCCESS; @@ -2255,7 +2256,7 @@ commit_mtr_for_a_while: ut_ad(!search_latch_locked); btr_pcur_store_position(&(plan->pcur), &mtr); - mtr_commit(&mtr); + mtr.commit(); mtr_has_extra_clust_latch = FALSE; ut_ad(!sync_check_iterate(dict_sync_check())); @@ -2271,7 +2272,7 @@ lock_wait_or_error: plan->stored_cursor_rec_processed = FALSE; btr_pcur_store_position(&(plan->pcur), &mtr); - mtr_commit(&mtr); + mtr.commit(); func_exit: #ifdef BTR_CUR_HASH_ADAPT @@ -3024,7 +3025,6 @@ row_sel_store_mysql_field_func( rec, offsets, dict_table_page_size(prebuilt->table), field_no, &len, heap); - //field_no, &len, heap, NULL); if (UNIV_UNLIKELY(!data)) { /* The externally stored field was not written @@ -4278,7 +4278,7 @@ row_search_mvcc( goto func_exit; } - mtr_start(&mtr); + mtr.start(); #ifdef BTR_CUR_HASH_ADAPT /*-------------------------------------------------------------*/ @@ -4327,7 +4327,7 @@ row_search_mvcc( a page latch that was acquired by row_sel_try_search_shortcut_for_mysql(). The latch will not be released until - mtr_commit(&mtr). */ + mtr.commit(). */ ut_ad(!rec_get_deleted_flag(rec, comp)); if (prebuilt->idx_cond) { @@ -4364,7 +4364,7 @@ row_search_mvcc( } shortcut_match: - mtr_commit(&mtr); + mtr.commit(); /* NOTE that we do NOT store the cursor position */ @@ -4377,7 +4377,7 @@ row_search_mvcc( case SEL_EXHAUSTED: shortcut_mismatch: - mtr_commit(&mtr); + mtr.commit(); err = DB_RECORD_NOT_FOUND; @@ -4395,8 +4395,8 @@ row_search_mvcc( ut_ad(0); } - mtr_commit(&mtr); - mtr_start(&mtr); + mtr.commit(); + mtr.start(); rw_lock_s_unlock(btr_get_search_latch(index)); } @@ -5369,7 +5369,7 @@ requires_clust_rec: /* Decide whether to prefetch extra rows. At this point, the clustered index record is protected by a page latch that was acquired when pcur was positioned. - The latch will not be released until mtr_commit(&mtr). */ + The latch will not be released until mtr.commit(). */ if ((match_mode == ROW_SEL_EXACT || prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD) @@ -5561,10 +5561,10 @@ next_rec: btr_pcur_store_position(pcur, &mtr); } - mtr_commit(&mtr); + mtr.commit(); mtr_has_extra_clust_latch = FALSE; - mtr_start(&mtr); + mtr.start(); if (!spatial_search && sel_restore_position_for_mysql(&same_user_rec, @@ -5622,7 +5622,7 @@ lock_wait_or_error: } lock_table_wait: - mtr_commit(&mtr); + mtr.commit(); mtr_has_extra_clust_latch = FALSE; trx->error_state = err; @@ -5639,7 +5639,7 @@ lock_table_wait: /* It was a lock wait, and it ended */ thr->lock_state = QUE_THR_LOCK_NOLOCK; - mtr_start(&mtr); + mtr.start(); /* Table lock waited, go try to obtain table lock again */ @@ -5691,7 +5691,7 @@ normal_return: /*-------------------------------------------------------------*/ que_thr_stop_for_mysql_no_error(thr, trx); - mtr_commit(&mtr); + mtr.commit(); /* Rollback blocking transactions from hit list for high priority transaction, if any. We should not be holding latches here as diff --git a/storage/innobase/row/row0umod.cc b/storage/innobase/row/row0umod.cc index 3dcffd1125a..76ad0815119 100644 --- a/storage/innobase/row/row0umod.cc +++ b/storage/innobase/row/row0umod.cc @@ -624,13 +624,13 @@ row_undo_mod_del_unmark_sec_and_undo_update( ut_ad(trx->id != 0); - /* FIXME: Currently we do a 2-pass search for the undo due to - avoid undel-mark a wrong rec in rolling back in partial update. - Later, we could log some info in secondary index updates to avoid - this. */ if (dict_index_is_spatial(index)) { + /* FIXME: Currently we do a 2-pass search for the undo + due to avoid undel-mark a wrong rec in rolling back in + partial update. Later, we could log some info in + secondary index updates to avoid this. */ ut_ad(mode & BTR_MODIFY_LEAF); - mode |= BTR_RTREE_DELETE_MARK; + mode |= BTR_RTREE_DELETE_MARK; } try_again: diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 0d0e908fdc3..aefe7e6dc96 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2017, MariaDB Corporation. +Copyright (c) 2015, 2018, MariaDB Corporation. 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 @@ -319,9 +319,20 @@ row_upd_check_references_constraints( But the counter on the table protects 'foreign' from being dropped while the check is running. */ + if (foreign_table) { + my_atomic_addlint( + &foreign_table->n_foreign_key_checks_running, + 1); + } + err = row_ins_check_foreign_constraint( FALSE, foreign, table, entry, thr); + if (foreign_table) { + my_atomic_addlint( + &foreign_table->n_foreign_key_checks_running, + -1); + } if (ref_table != NULL) { dict_table_close(ref_table, FALSE, FALSE); } @@ -342,11 +353,6 @@ func_exit: mem_heap_free(heap); DEBUG_SYNC_C("foreign_constraint_check_for_update_done"); - - DBUG_EXECUTE_IF("row_upd_cascade_lock_wait_err", - err = DB_LOCK_WAIT; - DBUG_SET("-d,row_upd_cascade_lock_wait_err");); - DBUG_RETURN(err); } @@ -469,9 +475,8 @@ wsrep_must_process_fk(const upd_node_t* node, const trx_t* trx) return false; } - const upd_node_t* parent = static_cast<const upd_node_t*>(node->common.parent); - - return parent->cascade_upd_nodes->empty(); + return static_cast<upd_node_t*>(node->common.parent)->cascade_node + == node; } #endif /* WITH_WSREP */ @@ -1261,7 +1266,7 @@ row_upd_index_replace_new_col_val( } len = dtype_get_at_most_n_mbchars(col->prtype, - col->mbminmaxlen, + col->mbminlen, col->mbmaxlen, field->prefix_len, len, (const char*) data); @@ -1514,12 +1519,7 @@ row_upd_replace_vcol( dfield_copy_data(dfield, upd_field->old_v_val); } - dfield_get_type(dfield)->mtype = - upd_field->new_val.type.mtype; - dfield_get_type(dfield)->prtype = - upd_field->new_val.type.prtype; - dfield_get_type(dfield)->mbminmaxlen = - upd_field->new_val.type.mbminmaxlen; + dfield->type = upd_field->new_val.type; break; } } @@ -2108,6 +2108,7 @@ row_upd_eval_new_vals( @param[in] update an update vector if it is update @param[in] thd mysql thread handle @param[in,out] mysql_table mysql table object */ +static void row_upd_store_v_row( upd_node_t* node, @@ -2155,7 +2156,6 @@ row_upd_store_v_row( cascade update. And virtual column can't be affected, so it is Ok to set it to NULL */ - ut_ad(!node->cascade_top); dfield_set_null(dfield); } else { dfield_t* vfield @@ -2250,25 +2250,6 @@ row_upd_store_row( } /***********************************************************//** -Print a MBR data from disk */ -static -void -srv_mbr_print(const byte* data) -{ - double a, b, c, d; - a = mach_double_read(data); - data += sizeof(double); - b = mach_double_read(data); - data += sizeof(double); - c = mach_double_read(data); - data += sizeof(double); - d = mach_double_read(data); - - ib::info() << "GIS MBR INFO: " << a << " and " << b << ", " << c - << ", " << d << "\n"; -} - -/***********************************************************//** Updates a secondary index entry of a row. @return DB_SUCCESS if operation successfully completed, else error code or DB_LOCK_WAIT */ @@ -2431,8 +2412,6 @@ row_upd_sec_index_entry( << " of table " << index->table->name << " was not found on update: " << *entry << " at: " << rec_index_print(rec, index); - if (entry->fields[0].data) - srv_mbr_print((unsigned char*)entry->fields[0].data); #ifdef UNIV_DEBUG mtr_commit(&mtr); mtr_start(&mtr); @@ -2663,7 +2642,9 @@ row_upd_clust_rec_by_insert( que_thr_t* thr, /*!< in: query thread */ ibool referenced,/*!< in: TRUE if index may be referenced in a foreign key constraint */ - ibool foreign, /*!< in: TRUE if index is foreign key index */ +#ifdef WITH_WSREP + bool foreign,/*!< in: whether this is a foreign key */ +#endif mtr_t* mtr) /*!< in/out: mtr; gets committed here */ { mem_heap_t* heap; @@ -2875,15 +2856,14 @@ row_upd_clust_rec( down the index tree */ mtr->start(); - mtr->set_named_space(index->space); - /* Disable REDO logging as lifetime of temp-tables is limited to - server or connection lifetime and so REDO information is not needed - on restart for recovery. - Disable locking as temp-tables are not shared across connection. */ - if (dict_table_is_temporary(index->table)) { + if (index->table->is_temporary()) { + /* Disable locking, because temporary tables are never + shared between transactions or connections. */ flags |= BTR_NO_LOCKING_FLAG; mtr->set_log_mode(MTR_LOG_NO_REDO); + } else { + mtr->set_named_space(index->space); } /* NOTE: this transaction has an s-lock or x-lock on the record and @@ -2952,7 +2932,9 @@ row_upd_del_mark_clust_rec( ibool referenced, /*!< in: TRUE if index may be referenced in a foreign key constraint */ - ibool foreign,/*!< in: TRUE if index is foreign key index */ +#ifdef WITH_WSREP + bool foreign,/*!< in: whether this is a foreign key */ +#endif mtr_t* mtr) /*!< in: mtr; gets committed here */ { btr_pcur_t* pcur; @@ -3044,7 +3026,6 @@ row_upd_clust_step( ulint* offsets; ibool referenced; ulint flags; - ibool foreign = FALSE; trx_t* trx = thr_get_trx(thr); rec_offs_init(offsets_); @@ -3054,8 +3035,7 @@ row_upd_clust_step( referenced = row_upd_index_is_referenced(index, trx); #ifdef WITH_WSREP - foreign = wsrep_row_upd_index_is_foreign( - index, thr_get_trx(thr)); + const bool foreign = wsrep_row_upd_index_is_foreign(index, trx); #endif pcur = node->pcur; @@ -3063,7 +3043,6 @@ row_upd_clust_step( /* We have to restore the cursor to its position */ mtr.start(); - mtr.set_named_space(index->space); if (dict_table_is_temporary(node->table)) { /* Disable locking, because temporary tables are @@ -3075,6 +3054,7 @@ row_upd_clust_step( mtr.set_log_mode(MTR_LOG_NO_REDO); } else { flags = node->table->no_rollback() ? BTR_NO_ROLLBACK : 0; + mtr.set_named_space(index->space); } /* If the restoration does not succeed, then the same @@ -3161,7 +3141,11 @@ row_upd_clust_step( if (node->is_delete) { err = row_upd_del_mark_clust_rec( - node, index, offsets, thr, referenced, foreign, &mtr); + node, index, offsets, thr, referenced, +#ifdef WITH_WSREP + foreign, +#endif + &mtr); if (err == DB_SUCCESS) { node->state = UPD_NODE_UPDATE_ALL_SEC; @@ -3207,7 +3191,11 @@ row_upd_clust_step( externally! */ err = row_upd_clust_rec_by_insert( - node, index, thr, referenced, foreign, &mtr); + node, index, thr, referenced, +#ifdef WITH_WSREP + foreign, +#endif + &mtr); if (err != DB_SUCCESS) { goto exit_func; @@ -3447,56 +3435,3 @@ error_handling: DBUG_RETURN(thr); } - -#ifndef DBUG_OFF - -/** Ensure that the member cascade_upd_nodes has only one update node -for each of the tables. This is useful for testing purposes. */ -void upd_node_t::check_cascade_only_once() -{ - DBUG_ENTER("upd_node_t::check_cascade_only_once"); - - dbug_trace(); - - for (upd_cascade_t::const_iterator i = cascade_upd_nodes->begin(); - i != cascade_upd_nodes->end(); ++i) { - - const upd_node_t* update_node = *i; - std::string table_name(update_node->table->name.m_name); - ulint count = 0; - - for (upd_cascade_t::const_iterator j - = cascade_upd_nodes->begin(); - j != cascade_upd_nodes->end(); ++j) { - - const upd_node_t* node = *j; - - if (table_name == node->table->name.m_name) { - DBUG_ASSERT(count++ == 0); - } - } - } - - DBUG_VOID_RETURN; -} - -/** Print information about this object into the trace log file. */ -void upd_node_t::dbug_trace() -{ - DBUG_ENTER("upd_node_t::dbug_trace"); - - for (upd_cascade_t::const_iterator i = cascade_upd_nodes->begin(); - i != cascade_upd_nodes->end(); ++i) { - DBUG_LOG("upd_node_t", "cascade_upd_nodes: Cascade to table: " - << (*i)->table->name); - } - - for (upd_cascade_t::const_iterator j = new_upd_nodes->begin(); - j != new_upd_nodes->end(); ++j) { - DBUG_LOG("upd_node_t", "new_upd_nodes: Cascade to table: " - << (*j)->table->name); - } - - DBUG_VOID_RETURN; -} -#endif /* !DBUG_OFF */ diff --git a/storage/innobase/row/row0vers.cc b/storage/innobase/row/row0vers.cc index 23ba751ea67..31cef0bad2d 100644 --- a/storage/innobase/row/row0vers.cc +++ b/storage/innobase/row/row0vers.cc @@ -1,7 +1,7 @@ /***************************************************************************** -Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -45,24 +45,31 @@ Created 2/6/1997 Heikki Tuuri #include "lock0lock.h" #include "row0mysql.h" -/** Check whether all non-virtual columns in a virtual index match that of in -the cluster index -@param[in] index the secondary index -@param[in] row the cluster index row in dtuple form -@param[in] ext externally stored column prefix or NULL -@param[in] ientry the secondary index entry -@param[in,out] heap heap used to build virtual dtuple -@param[in,out] n_non_v_col number of non-virtual columns in the index -@return true if all matches, false otherwise */ +/** Check whether all non-virtual index fields are equal. +@param[in] index the secondary index +@param[in] a first index entry to compare +@param[in] b second index entry to compare +@return whether all non-virtual fields are equal */ static bool -row_vers_non_vc_match( - dict_index_t* index, - const dtuple_t* row, - const row_ext_t* ext, - const dtuple_t* ientry, - mem_heap_t* heap, - ulint* n_non_v_col); +row_vers_non_virtual_fields_equal( + const dict_index_t* index, + const dfield_t* a, + const dfield_t* b) +{ + const dict_field_t* end = &index->fields[index->n_fields]; + + for (const dict_field_t* ifield = index->fields; ifield != end; + ifield++) { + if (!dict_col_is_virtual(ifield->col) + && cmp_dfield_dfield(a++, b++)) { + return false; + } + } + + return true; +} + /** Determine if an active transaction has inserted or modified a secondary index record. @param[in] clust_rec clustered index record @@ -233,15 +240,29 @@ row_vers_impl_x_locked_low( } if (!cur_vrow) { - ulint n_non_v_col = 0; + /* Build index entry out of row */ + entry = row_build_index_entry(row, ext, index, + heap); + + /* entry could only be NULL (the + clustered index record could contain + BLOB pointers that are NULL) if we + were accessing a freshly inserted + record before it was fully inserted. + prev_version cannot possibly be such + an incomplete record, because its + transaction would have to be committed + in order for later versions of the + record to be able to exist. */ + ut_ad(entry); /* If the indexed virtual columns has changed, there must be log record to generate vrow. Otherwise, it is not changed, so no need to compare */ - if (row_vers_non_vc_match( - index, row, ext, ientry, heap, - &n_non_v_col) == 0) { + if (!row_vers_non_virtual_fields_equal( + index, + ientry->fields, entry->fields)) { if (rec_del != vers_del) { break; } @@ -258,12 +279,14 @@ row_vers_impl_x_locked_low( entry = row_build_index_entry(row, ext, index, heap); - /* entry may be NULL if a record was inserted in place - of a deleted record, and the BLOB pointers of the new - record were not initialized yet. But in that case, - prev_version should be NULL. */ - - ut_a(entry != NULL); + /* entry could only be NULL (the clustered index + record could contain BLOB pointers that are NULL) if + we were accessing a freshly inserted record before it + was fully inserted. prev_version cannot possibly be + such an incomplete record, because its transaction + would have to be committed in order for later versions + of the record to be able to exist. */ + ut_ad(entry); /* If we get here, we know that the trx_id transaction modified prev_version. Let us check if prev_version @@ -409,61 +432,6 @@ row_vers_must_preserve_del_marked( return(!purge_sys->view.changes_visible(trx_id, name)); } -/** Check whether all non-virtual columns in a virtual index match that of in -the cluster index -@param[in] index the secondary index -@param[in] row the cluster index row in dtuple form -@param[in] ext externally stored column prefix or NULL -@param[in] ientry the secondary index entry -@param[in,out] heap heap used to build virtual dtuple -@param[in,out] n_non_v_col number of non-virtual columns in the index -@return true if all matches, false otherwise */ -static -bool -row_vers_non_vc_match( - dict_index_t* index, - const dtuple_t* row, - const row_ext_t* ext, - const dtuple_t* ientry, - mem_heap_t* heap, - ulint* n_non_v_col) -{ - const dfield_t* field1; - dfield_t* field2; - ulint n_fields = dtuple_get_n_fields(ientry); - ulint ret = true; - - *n_non_v_col = 0; - - /* Build index entry out of row */ - dtuple_t* nentry = row_build_index_entry(row, ext, index, heap); - - for (ulint i = 0; i < n_fields; i++) { - const dict_field_t* ind_field = dict_index_get_nth_field( - index, i); - - const dict_col_t* col = ind_field->col; - - /* Only check non-virtual columns */ - if (dict_col_is_virtual(col)) { - continue; - } - - if (ret) { - field1 = dtuple_get_nth_field(ientry, i); - field2 = dtuple_get_nth_field(nentry, i); - - if (cmp_dfield_dfield(field1, field2) != 0) { - ret = false; - } - } - - (*n_non_v_col)++; - } - - return(ret); -} - /** build virtual column value from current cluster index record data @param[in,out] row the cluster index row in dtuple form @param[in] clust_index clustered index @@ -614,8 +582,7 @@ that of current cluster index record, which is recreated from information stored in undo log @param[in] in_purge called by purge thread @param[in] rec record in the clustered index -@param[in] row the cluster index row in dtuple form -@param[in] ext externally stored column prefix or NULL +@param[in] icentry the index entry built from a cluster row @param[in] clust_index cluster index @param[in] clust_offsets offsets on the cluster record @param[in] index the secondary index @@ -631,8 +598,7 @@ bool row_vers_vc_matches_cluster( bool in_purge, const rec_t* rec, - const dtuple_t* row, - row_ext_t* ext, + const dtuple_t* icentry, dict_index_t* clust_index, ulint* clust_offsets, dict_index_t* index, @@ -657,15 +623,27 @@ row_vers_vc_matches_cluster( dfield_t* field2; ulint i; - tuple_heap = mem_heap_create(1024); - /* First compare non-virtual columns (primary keys) */ - if (!row_vers_non_vc_match(index, row, ext, ientry, tuple_heap, - &n_non_v_col)) { - mem_heap_free(tuple_heap); - return(false); + ut_ad(index->n_fields == n_fields); + ut_ad(n_fields == dtuple_get_n_fields(icentry)); + { + const dfield_t* a = ientry->fields; + const dfield_t* b = icentry->fields; + + for (const dict_field_t *ifield = index->fields, + *const end = &index->fields[index->n_fields]; + ifield != end; ifield++, a++, b++) { + if (!dict_col_is_virtual(ifield->col)) { + if (cmp_dfield_dfield(a, b)) { + return false; + } + n_non_v_col++; + } + } } + tuple_heap = mem_heap_create(1024); + ut_ad(n_fields > n_non_v_col); *vrow = dtuple_create_with_vcol(v_heap ? v_heap : tuple_heap, 0, num_v); @@ -934,27 +912,28 @@ row_vers_old_has_index_entry( entry = row_build_index_entry( row, ext, index, heap); if (entry && !dtuple_coll_cmp(ientry, entry)) { - - mem_heap_free(heap); - - if (v_heap) { - mem_heap_free(v_heap); - } - - return(TRUE); + goto safe_to_purge; } } else { - if (row_vers_vc_matches_cluster( - also_curr, rec, row, ext, clust_index, - clust_offsets, index, ientry, roll_ptr, - trx_id, NULL, &vrow, mtr)) { - mem_heap_free(heap); - - if (v_heap) { - mem_heap_free(v_heap); - } - - return(TRUE); + /* Build index entry out of row */ + entry = row_build_index_entry(row, ext, index, heap); + /* entry could only be NULL if + the clustered index record is an uncommitted + inserted record whose BLOBs have not been + written yet. The secondary index record + can be safely removed, because it cannot + possibly refer to this incomplete + clustered index record. (Insert would + always first be completed for the + clustered index record, then proceed to + secondary indexes.) */ + + if (entry && row_vers_vc_matches_cluster( + also_curr, rec, entry, + clust_index, clust_offsets, + index, ientry, roll_ptr, + trx_id, NULL, &vrow, mtr)) { + goto safe_to_purge; } } clust_offsets = rec_get_offsets(rec, clust_index, NULL, @@ -987,7 +966,7 @@ row_vers_old_has_index_entry( a different binary value in a char field, but the collation identifies the old and new value anyway! */ if (entry && !dtuple_coll_cmp(ientry, entry)) { - +safe_to_purge: mem_heap_free(heap); if (v_heap) { @@ -1084,13 +1063,7 @@ row_vers_old_has_index_entry( and new value anyway! */ if (entry && !dtuple_coll_cmp(ientry, entry)) { - - mem_heap_free(heap); - if (v_heap) { - mem_heap_free(v_heap); - } - - return(TRUE); + goto safe_to_purge; } } diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 19be088912a..9989a24c708 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -78,10 +78,7 @@ Created 10/8/1995 Heikki Tuuri #include "fil0crypt.h" #include "fil0pagecompress.h" #include "btr0scrub.h" -#ifdef WITH_WSREP -extern int wsrep_debug; -extern int wsrep_trx_is_aborting(void *thd_ptr); -#endif + /* The following is the maximum allowed duration of a lock wait. */ UNIV_INTERN ulong srv_fatal_semaphore_wait_threshold = DEFAULT_SRV_FATAL_SEMAPHORE_TIMEOUT; diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index df739ebb580..0688f871e37 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -627,6 +627,9 @@ trx_rollback_active( roll_node_t* roll_node; dict_table_t* table; ibool dictionary_locked = FALSE; + const trx_id_t trx_id = trx->id; + + ut_ad(trx_id); heap = mem_heap_create(512); @@ -698,14 +701,13 @@ trx_rollback_active( } } + ib::info() << "Rolled back recovered transaction " << trx_id; + func_exit: if (dictionary_locked) { row_mysql_unlock_data_dictionary(trx); } - ib::info() << "Rollback of trx with id " << ib::hex(trx->id) - << " completed"; - mem_heap_free(heap); trx_roll_crash_recv_trx = NULL; diff --git a/storage/innobase/trx/trx0undo.cc b/storage/innobase/trx/trx0undo.cc index 10c4d79209e..e3eb2595365 100644 --- a/storage/innobase/trx/trx0undo.cc +++ b/storage/innobase/trx/trx0undo.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2017, MariaDB Corporation. +Copyright (c) 2014, 2018, MariaDB Corporation. 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 diff --git a/storage/innobase/ut/ut0ut.cc b/storage/innobase/ut/ut0ut.cc index 25705cb0e2c..a8ff700847a 100644 --- a/storage/innobase/ut/ut0ut.cc +++ b/storage/innobase/ut/ut0ut.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1994, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -40,6 +40,9 @@ Created 5/11/1994 Heikki Tuuri #include "my_cpu.h" #ifdef _WIN32 +typedef VOID(WINAPI *time_fn)(LPFILETIME); +static time_fn ut_get_system_time_as_file_time = GetSystemTimeAsFileTime; + /*****************************************************************//** NOTE: The Windows epoch starts from 1601/01/01 whereas the Unix epoch starts from 1970/1/1. For selection of constant see: @@ -65,7 +68,7 @@ ut_gettimeofday( return(-1); } - GetSystemTimeAsFileTime(&ft); + ut_get_system_time_as_file_time(&ft); tm = (int64_t) ft.dwHighDateTime << 32; tm |= ft.dwLowDateTime; diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index c090ba49091..4aa207902a9 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -2149,11 +2149,16 @@ void ha_maria::start_bulk_insert(ha_rows rows, uint flags) safety net for now, we don't remove the test of file->state->records, because there is uncertainty on what will happen during repair if the two states disagree. + + We also have to check in case of transactional tables that the + user has not used LOCK TABLE on the table twice. */ if ((file->state->records == 0) && (share->state.state.records == 0) && can_enable_indexes && (!rows || rows >= MARIA_MIN_ROWS_TO_DISABLE_INDEXES) && - (file->lock.type == TL_WRITE || file->lock.type == TL_UNLOCK)) + (file->lock.type == TL_WRITE || file->lock.type == TL_UNLOCK) && + (!share->have_versioning || !share->now_transactional || + file->used_tables->use_count == 1)) { /** @todo for a single-row INSERT SELECT, we will go into repair, which diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index b965f5db34b..c91ba8e23f6 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -6166,7 +6166,7 @@ my_bool write_hook_for_undo_row_insert(enum translog_record_type type /** - @brief Upates "records" and calls the generic UNDO hook + @brief Updates "records" and calls the generic UNDO hook @return Operation status, always 0 (success) */ @@ -6316,8 +6316,8 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, uchar *buff, *dir; uint result; MARIA_PINNED_PAGE page_link; - enum pagecache_page_lock unlock_method; - enum pagecache_page_pin unpin_method; + enum pagecache_page_lock lock_method; + enum pagecache_page_pin pin_method; my_off_t end_of_page; uint error; DBUG_ENTER("_ma_apply_redo_insert_row_head_or_tail"); @@ -6345,8 +6345,8 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, fill it entirely with zeroes, then the REDO will put correct data on it. */ - unlock_method= PAGECACHE_LOCK_WRITE; - unpin_method= PAGECACHE_PIN; + lock_method= PAGECACHE_LOCK_WRITE; + pin_method= PAGECACHE_PIN; DBUG_ASSERT(rownr == 0 && new_page); if (rownr != 0 || !new_page) @@ -6361,8 +6361,8 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, } else { - unlock_method= PAGECACHE_LOCK_LEFT_WRITELOCKED; - unpin_method= PAGECACHE_PIN_LEFT_PINNED; + lock_method= PAGECACHE_LOCK_LEFT_WRITELOCKED; + pin_method= PAGECACHE_PIN_LEFT_PINNED; share->pagecache->readwrite_flags&= ~MY_WME; buff= pagecache_read(share->pagecache, &info->dfile, @@ -6463,11 +6463,11 @@ uint _ma_apply_redo_insert_row_head_or_tail(MARIA_HA *info, LSN lsn, this group, for this page, would be skipped) and unpin then. */ result= 0; - if (unlock_method == PAGECACHE_LOCK_WRITE && + if (lock_method == PAGECACHE_LOCK_WRITE && pagecache_write(share->pagecache, &info->dfile, page, 0, buff, PAGECACHE_PLAIN_PAGE, - unlock_method, unpin_method, + lock_method, pin_method, PAGECACHE_WRITE_DELAY, &page_link.link, LSN_IMPOSSIBLE)) result= my_errno; @@ -6488,7 +6488,7 @@ crashed_file: _ma_set_fatal_error(share, HA_ERR_WRONG_IN_RECORD); err: error= my_errno; - if (unlock_method == PAGECACHE_LOCK_LEFT_WRITELOCKED) + if (lock_method == PAGECACHE_LOCK_LEFT_WRITELOCKED) pagecache_unlock_by_link(share->pagecache, page_link.link, PAGECACHE_LOCK_WRITE_UNLOCK, PAGECACHE_UNPIN, LSN_IMPOSSIBLE, diff --git a/storage/maria/ma_page.c b/storage/maria/ma_page.c index c8901e6d736..0e83a89917d 100644 --- a/storage/maria/ma_page.c +++ b/storage/maria/ma_page.c @@ -224,17 +224,35 @@ my_bool _ma_write_keypage(MARIA_PAGE *page, enum pagecache_page_lock lock, #endif page_cleanup(share, page); - res= pagecache_write(share->pagecache, - &share->kfile, - (pgcache_page_no_t) (page->pos / block_size), - level, buff, share->page_type, - lock, - lock == PAGECACHE_LOCK_LEFT_WRITELOCKED ? - PAGECACHE_PIN_LEFT_PINNED : - (lock == PAGECACHE_LOCK_WRITE_UNLOCK ? - PAGECACHE_UNPIN : PAGECACHE_PIN), - PAGECACHE_WRITE_DELAY, &page_link.link, - LSN_IMPOSSIBLE); + { + PAGECACHE_BLOCK_LINK **link; + enum pagecache_page_pin pin; + if (lock == PAGECACHE_LOCK_LEFT_WRITELOCKED) + { + pin= PAGECACHE_PIN_LEFT_PINNED; + link= &page_link.link; + } + else if (lock == PAGECACHE_LOCK_WRITE_UNLOCK) + { + pin= PAGECACHE_UNPIN; + /* + We unlock this page so link should be 0 to prevent it usage + even accidentally + */ + link= NULL; + } + else + { + pin= PAGECACHE_PIN; + link= &page_link.link; + } + res= pagecache_write(share->pagecache, + &share->kfile, + (pgcache_page_no_t) (page->pos / block_size), + level, buff, share->page_type, + lock, pin, PAGECACHE_WRITE_DELAY, link, + LSN_IMPOSSIBLE); + } if (lock == PAGECACHE_LOCK_WRITE) { diff --git a/storage/maria/ma_state.c b/storage/maria/ma_state.c index 05bc8a8acb8..71e1e8a67a6 100644 --- a/storage/maria/ma_state.c +++ b/storage/maria/ma_state.c @@ -58,6 +58,7 @@ my_bool _ma_setup_live_state(MARIA_HA *info) MARIA_USED_TABLES *tables; MARIA_STATE_HISTORY *history; DBUG_ENTER("_ma_setup_live_state"); + DBUG_PRINT("enter", ("info: %p", info)); DBUG_ASSERT(share->lock_key_trees); @@ -110,6 +111,8 @@ my_bool _ma_setup_live_state(MARIA_HA *info) end: info->state_start= &tables->state_start; info->state= &tables->state_current; + info->used_tables= tables; + tables->use_count++; /* Mark in transaction state if we are not using transid (versioning) @@ -118,6 +121,7 @@ end: */ tables->state_current.no_transid|= !(info->row_flag & ROW_FLAG_TRANSID); + DBUG_PRINT("exit", ("tables: %p info->state: %p", tables, info->state)); DBUG_RETURN(0); } @@ -241,9 +245,10 @@ void _ma_reset_state(MARIA_HA *info) DBUG_ENTER("_ma_reset_state"); /* Always true if share->now_transactional is set */ - if (history) + if (history && share->have_versioning) { MARIA_STATE_HISTORY *next; + DBUG_PRINT("info", ("resetting history")); /* Set the current history to current state */ share->state_history->state= share->state.state; @@ -255,7 +260,7 @@ void _ma_reset_state(MARIA_HA *info) my_free(history); } share->state_history->next= 0; - share->state_history->trid= 0; /* Visibile for all */ + share->state_history->trid= 0; /* Visible for all */ } DBUG_VOID_RETURN; } @@ -597,7 +602,7 @@ void _ma_remove_table_from_trnman(MARIA_SHARE *share, TRN *trn) SYNOPSIS _ma_get_status() - param Pointer to Myisam handler + param Pointer to Aria handler concurrent_insert Set to 1 if we are going to do concurrent inserts (THR_WRITE_CONCURRENT_INSERT was used) */ @@ -627,6 +632,8 @@ void _ma_block_get_status(void* param, my_bool concurrent_insert) my_bool _ma_block_start_trans(void* param) { MARIA_HA *info=(MARIA_HA*) param; + DBUG_ENTER("_ma_block_start_trans"); + if (info->s->lock_key_trees) { /* @@ -634,7 +641,7 @@ my_bool _ma_block_start_trans(void* param) out of memory conditions) TODO: Fix this by having one extra state pre-allocated */ - return _ma_setup_live_state(info); + DBUG_RETURN(_ma_setup_live_state(info)); } else { @@ -663,9 +670,9 @@ my_bool _ma_block_start_trans(void* param) Assume for now that this doesn't fail (It can only fail in out of memory conditions) */ - return maria_create_trn_hook(info) != 0; + DBUG_RETURN(maria_create_trn_hook(info) != 0); } - return 0; + DBUG_RETURN(0); } @@ -697,7 +704,7 @@ my_bool _ma_block_check_status(void *param __attribute__((unused))) my_bool _ma_block_start_trans_no_versioning(void* param) { MARIA_HA *info=(MARIA_HA*) param; - DBUG_ENTER("_ma_block_get_status_no_version"); + DBUG_ENTER("_ma_block_start_trans_no_versioning"); DBUG_ASSERT(info->s->base.born_transactional && !info->s->lock_key_trees); info->state->changed= 0; /* from _ma_reset_update_flag() */ @@ -722,6 +729,8 @@ my_bool _ma_block_start_trans_no_versioning(void* param) void maria_versioning(MARIA_HA *info, my_bool versioning) { MARIA_SHARE *share= info->s; + DBUG_ENTER("maria_versioning"); + /* For now, this is a hack */ if (share->have_versioning) { @@ -738,6 +747,7 @@ void maria_versioning(MARIA_HA *info, my_bool versioning) info->state= &share->state.state; /* Change global values by default */ info->state_start= info->state; /* Initial values */ } + DBUG_VOID_RETURN; } diff --git a/storage/maria/ma_state.h b/storage/maria/ma_state.h index 5ff6dc26337..a86aada94fd 100644 --- a/storage/maria/ma_state.h +++ b/storage/maria/ma_state.h @@ -34,6 +34,7 @@ typedef struct st_used_tables { struct st_maria_share *share; MARIA_STATUS_INFO state_current; MARIA_STATUS_INFO state_start; + uint use_count; } MARIA_USED_TABLES; diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index ffebb8c0ac9..66bf77e0a80 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -341,7 +341,7 @@ err: for (j=0 ; j < share->base.keys ; j++) maria_flush_bulk_insert(info, j); } - info->errkey= (int) i; + info->errkey= i < share->base.keys ? (int) i : -1; /* We delete keys in the reverse order of insertion. This is the order that a rollback would do and is important for CLR_ENDs generated by diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index 6f8964fd479..716c0ef824c 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -600,6 +600,7 @@ struct st_maria_handler struct st_ma_transaction *trn; /* Pointer to active transaction */ MARIA_STATUS_INFO *state, state_save; MARIA_STATUS_INFO *state_start; /* State at start of transaction */ + MARIA_USED_TABLES *used_tables; MARIA_ROW cur_row; /* The active row that we just read */ MARIA_ROW new_row; /* Storage for a row during update */ MARIA_KEY last_key; /* Last found key */ @@ -1182,7 +1183,7 @@ extern ulonglong transid_get_packed(MARIA_SHARE *share, const uchar *from); #ifdef IDENTICAL_PAGES_AFTER_RECOVERY void page_cleanup(MARIA_SHARE *share, MARIA_PAGE *page) #else -#define page_cleanup(A,B) while (0) +#define page_cleanup(A,B) do { } while (0) #endif extern MARIA_KEY *_ma_make_key(MARIA_HA *info, MARIA_KEY *int_key, uint keynr, diff --git a/storage/maria/unittest/ma_test_loghandler_multigroup-t.c b/storage/maria/unittest/ma_test_loghandler_multigroup-t.c index 69bc2f70f8c..cffe188e855 100644 --- a/storage/maria/unittest/ma_test_loghandler_multigroup-t.c +++ b/storage/maria/unittest/ma_test_loghandler_multigroup-t.c @@ -233,7 +233,7 @@ int main(int argc __attribute__((unused)), char *argv[]) 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55 }; - uchar *long_buffer= malloc(LONG_BUFFER_SIZE + LSN_STORE_SIZE * 2 + 2); + uchar *long_buffer; char **default_argv; PAGECACHE pagecache; LSN lsn, lsn_base, first_lsn; @@ -255,6 +255,7 @@ int main(int argc __attribute__((unused)), char *argv[]) } #endif + long_buffer= malloc(LONG_BUFFER_SIZE + LSN_STORE_SIZE * 2 + 2); load_defaults("my", load_default_groups, &argc, &argv); default_argv= argv; get_options(&argc, &argv); @@ -758,9 +759,12 @@ err: if (maria_log_remove(maria_data_root)) exit(1); + free(long_buffer); + my_uuid_end(); my_free_open_file_info(); my_end(0); + return (MY_TEST(exit_status())); } diff --git a/storage/maria/unittest/ma_test_loghandler_nologs-t.c b/storage/maria/unittest/ma_test_loghandler_nologs-t.c index a6ccfd754de..310345f0885 100644 --- a/storage/maria/unittest/ma_test_loghandler_nologs-t.c +++ b/storage/maria/unittest/ma_test_loghandler_nologs-t.c @@ -191,6 +191,8 @@ int main(int argc __attribute__((unused)), char *argv[]) if (maria_log_remove(maria_data_root)) exit(1); + free(long_buffer); + my_uuid_end(); my_free_open_file_info(); my_end(0); diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c index 372acc52fae..1ca252c2505 100644 --- a/storage/myisam/mi_check.c +++ b/storage/myisam/mi_check.c @@ -4792,8 +4792,7 @@ static int replace_data_file(HA_CHECK *param, MI_INFO *info, File new_file) */ if (info->s->file_map) { - (void) my_munmap((char*) info->s->file_map, - (size_t) info->s->mmaped_length); + (void) my_munmap((char*) info->s->file_map, info->s->mmaped_length); info->s->file_map= NULL; } diff --git a/storage/myisam/mi_dynrec.c b/storage/myisam/mi_dynrec.c index c4baca3d89f..cb49ded0c20 100644 --- a/storage/myisam/mi_dynrec.c +++ b/storage/myisam/mi_dynrec.c @@ -95,7 +95,7 @@ my_bool mi_dynmap_file(MI_INFO *info, my_off_t size) #if defined(HAVE_MADVISE) madvise((char*) info->s->file_map, size, MADV_RANDOM); #endif - info->s->mmaped_length= size; + info->s->mmaped_length= (size_t) size; info->s->file_read= mi_mmap_pread; info->s->file_write= mi_mmap_pwrite; DBUG_RETURN(0); @@ -118,8 +118,7 @@ int mi_munmap_file(MI_INFO *info) { int ret; DBUG_ENTER("mi_unmap_file"); - if ((ret= my_munmap((void*) info->s->file_map, - (size_t) info->s->mmaped_length))) + if ((ret= my_munmap((void*) info->s->file_map, info->s->mmaped_length))) DBUG_RETURN(ret); info->s->file_read= mi_nommap_pread; info->s->file_write= mi_nommap_pwrite; diff --git a/storage/myisam/mi_locking.c b/storage/myisam/mi_locking.c index 1921926463e..4fd287c6038 100644 --- a/storage/myisam/mi_locking.c +++ b/storage/myisam/mi_locking.c @@ -1,5 +1,5 @@ -/* - Copyright (c) 2000, 2010, Oracle and/or its affiliates +/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + Copyright (c) 2009, 2018, MariaDB Corporation 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 @@ -113,6 +113,8 @@ int mi_lock_database(MI_INFO *info, int lock_type) share->changed=0; if (myisam_flush) { + if (share->file_map) + my_msync(info->dfile, share->file_map, share->mmaped_length, MS_SYNC); if (mysql_file_sync(share->kfile, MYF(0))) mark_crashed= error= my_errno; if (mysql_file_sync(info->dfile, MYF(0))) @@ -526,6 +528,8 @@ int _mi_writeinfo(register MI_INFO *info, uint operation) #ifdef _WIN32 if (myisam_flush) { + if (share->file_map) + my_msync(info->dfile, share->file_map, share->mmaped_length, MS_SYNC); mysql_file_sync(share->kfile, 0); mysql_file_sync(info->dfile, 0); } diff --git a/storage/myisam/mi_packrec.c b/storage/myisam/mi_packrec.c index fc32bb7e518..242bc82bd16 100644 --- a/storage/myisam/mi_packrec.c +++ b/storage/myisam/mi_packrec.c @@ -1551,7 +1551,7 @@ void _mi_unmap_file(MI_INFO *info) { DBUG_ASSERT(info->s->options & HA_OPTION_COMPRESS_RECORD); - (void) my_munmap((char*) info->s->file_map, (size_t) info->s->mmaped_length); + (void) my_munmap((char*) info->s->file_map, info->s->mmaped_length); if (myisam_mmap_size != SIZE_T_MAX) { diff --git a/storage/myisam/myisamdef.h b/storage/myisam/myisamdef.h index 0d718f0a22e..583f115c908 100644 --- a/storage/myisam/myisamdef.h +++ b/storage/myisam/myisamdef.h @@ -224,7 +224,7 @@ typedef struct st_mi_isam_share THR_LOCK lock; mysql_mutex_t intern_lock; /* Locking for use with _locking */ mysql_rwlock_t *key_root_lock; - my_off_t mmaped_length; + size_t mmaped_length; uint nonmmaped_inserts; /* counter of writing in non-mmaped area */ mysql_rwlock_t mmap_lock; diff --git a/storage/tokudb/CMakeLists.txt b/storage/tokudb/CMakeLists.txt index 7490f4e620b..702b2eaa2dd 100644 --- a/storage/tokudb/CMakeLists.txt +++ b/storage/tokudb/CMakeLists.txt @@ -1,7 +1,9 @@ -SET(TOKUDB_VERSION 5.6.37-82.2) +SET(TOKUDB_VERSION 5.6.38-83.0) # PerconaFT only supports x86-64 and cmake-2.8.9+ IF(CMAKE_VERSION VERSION_LESS "2.8.9") MESSAGE(STATUS "CMake 2.8.9 or higher is required by TokuDB") +ELSEIF(NOT HAVE_DLOPEN) + MESSAGE(STATUS "dlopen is required by TokuDB") ELSEIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" OR CMAKE_SYSTEM_PROCESSOR STREQUAL "amd64") # tokudb requires F_NOCACHE or O_DIRECT, and designated initializers diff --git a/storage/tokudb/PerconaFT/CMakeLists.txt b/storage/tokudb/PerconaFT/CMakeLists.txt index 1c9052c2a55..5c6d938808e 100644 --- a/storage/tokudb/PerconaFT/CMakeLists.txt +++ b/storage/tokudb/PerconaFT/CMakeLists.txt @@ -12,9 +12,14 @@ set(CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "") # detect when we are being built as a subproject if (DEFINED MYSQL_PROJECT_NAME_DOCSTRING) add_definitions( -DMYSQL_TOKUDB_ENGINE=1) + # Extended PFS instrumentation: + # -DTOKU_PFS_MUTEX_EXTENDED_CACHETABLEMMUTEX=1 + if (WITH_PERFSCHEMA_STORAGE_ENGINE) + add_definitions(-DTOKU_MYSQL_WITH_PFS) + endif () + include_directories(${CMAKE_SOURCE_DIR}/include) if ((CMAKE_BUILD_TYPE MATCHES "Debug") AND (CMAKE_CXX_FLAGS_DEBUG MATCHES " -DENABLED_DEBUG_SYNC")) - include_directories(${CMAKE_SOURCE_DIR}/include) include_directories(${CMAKE_SOURCE_DIR}/sql) endif () endif () diff --git a/storage/tokudb/PerconaFT/buildheader/make_tdb.cc b/storage/tokudb/PerconaFT/buildheader/make_tdb.cc index 0fa876f2bd8..95d6207edda 100644 --- a/storage/tokudb/PerconaFT/buildheader/make_tdb.cc +++ b/storage/tokudb/PerconaFT/buildheader/make_tdb.cc @@ -445,14 +445,15 @@ static void print_db_key_range_struct (void) { sort_and_dump_fields("db_key_range", false, NULL); } -static void print_db_lsn_struct (void) { - field_counter=0; - /* A dummy field to make sizeof(DB_LSN) equal in C and C++ */ - const char *extra[] = { "char dummy", NULL }; - sort_and_dump_fields("db_lsn", false, extra); +static void print_db_lsn_struct(void) { + field_counter = 0; + // FT-692 + STRUCT_SETUP(DB_LSN, file, "uint32_t %s"); + STRUCT_SETUP(DB_LSN, offset, "uint32_t %s"); + sort_and_dump_fields("db_lsn", false, NULL); } -static void print_dbt_struct (void) { +static void print_dbt_struct(void) { field_counter=0; #if 0 && DB_VERSION_MAJOR==4 && DB_VERSION_MINOR==1 STRUCT_SETUP(DBT, app_private, "void*%s"); diff --git a/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake b/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake index 0cd9a9c5941..385723aebc7 100644 --- a/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake +++ b/storage/tokudb/PerconaFT/cmake_modules/TokuSetupCompiler.cmake @@ -53,7 +53,13 @@ macro(set_cflags_if_supported) endforeach(flag) endmacro(set_cflags_if_supported) +if (NOT DEFINED MYSQL_PROJECT_NAME_DOCSTRING) + set (OPTIONAL_CFLAGS "${OPTIONAL_CFLAGS} -Wmissing-format-attribute") +endif() + ## disable some warnings +## missing-format-attribute causes warnings in some MySQL include files +## if the library is built as a part of TokuDB MySQL storage engine set_cflags_if_supported( -Wno-missing-field-initializers -Wstrict-null-sentinel @@ -61,7 +67,7 @@ set_cflags_if_supported( -Wswitch -Wtrampolines -Wlogical-op - -Wmissing-format-attribute + ${OPTIONAL_CFLAGS} -Wno-error=missing-format-attribute -Wno-error=address-of-array-temporary -Wno-error=tautological-constant-out-of-range-compare @@ -143,8 +149,8 @@ set_cflags_if_supported( -Wmissing-prototypes -Wmissing-declarations -Wpointer-arith - -Wmissing-format-attribute -Wshadow + ${OPTIONAL_CFLAGS} ## other flags to try: #-Wunsafe-loop-optimizations #-Wpointer-arith diff --git a/storage/tokudb/PerconaFT/ft/cachetable/background_job_manager.cc b/storage/tokudb/PerconaFT/ft/cachetable/background_job_manager.cc index 9119a49b081..c109185f973 100644 --- a/storage/tokudb/PerconaFT/ft/cachetable/background_job_manager.cc +++ b/storage/tokudb/PerconaFT/ft/cachetable/background_job_manager.cc @@ -42,6 +42,9 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "cachetable/background_job_manager.h" +toku_instr_key *bjm_jobs_lock_mutex_key; +toku_instr_key *bjm_jobs_wait_key; + struct background_job_manager_struct { bool accepting_jobs; uint32_t num_jobs; @@ -49,10 +52,10 @@ struct background_job_manager_struct { toku_mutex_t jobs_lock; }; -void bjm_init(BACKGROUND_JOB_MANAGER* pbjm) { +void bjm_init(BACKGROUND_JOB_MANAGER *pbjm) { BACKGROUND_JOB_MANAGER XCALLOC(bjm); - toku_mutex_init(&bjm->jobs_lock, 0); - toku_cond_init(&bjm->jobs_wait, NULL); + toku_mutex_init(*bjm_jobs_lock_mutex_key, &bjm->jobs_lock, nullptr); + toku_cond_init(*bjm_jobs_wait_key, &bjm->jobs_wait, nullptr); bjm->accepting_jobs = true; bjm->num_jobs = 0; *pbjm = bjm; diff --git a/storage/tokudb/PerconaFT/ft/cachetable/cachetable.cc b/storage/tokudb/PerconaFT/ft/cachetable/cachetable.cc index 54ef11eb1eb..b72edc8d231 100644 --- a/storage/tokudb/PerconaFT/ft/cachetable/cachetable.cc +++ b/storage/tokudb/PerconaFT/ft/cachetable/cachetable.cc @@ -58,6 +58,25 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "util/status.h" #include "util/context.h" +toku_instr_key *cachetable_m_mutex_key; +toku_instr_key *cachetable_ev_thread_lock_mutex_key; + +toku_instr_key *cachetable_m_list_lock_key; +toku_instr_key *cachetable_m_pending_lock_expensive_key; +toku_instr_key *cachetable_m_pending_lock_cheap_key; +toku_instr_key *cachetable_m_lock_key; + +toku_instr_key *cachetable_value_key; +toku_instr_key *cachetable_disk_nb_rwlock_key; + +toku_instr_key *cachetable_p_refcount_wait_key; +toku_instr_key *cachetable_m_flow_control_cond_key; +toku_instr_key *cachetable_m_ev_thread_cond_key; + +toku_instr_key *cachetable_disk_nb_mutex_key; +toku_instr_key *log_internal_lock_mutex_key; +toku_instr_key *eviction_thread_key; + /////////////////////////////////////////////////////////////////////////////////// // Engine status // @@ -780,18 +799,25 @@ void pair_init(PAIR p, p->checkpoint_complete_callback = write_callback.checkpoint_complete_callback; p->write_extraargs = write_callback.write_extraargs; - p->count = 0; // <CER> Is zero the correct init value? + p->count = 0; // <CER> Is zero the correct init value? p->refcount = 0; p->num_waiting_on_refs = 0; - toku_cond_init(&p->refcount_wait, NULL); + toku_cond_init(*cachetable_p_refcount_wait_key, &p->refcount_wait, nullptr); p->checkpoint_pending = false; p->mutex = list->get_mutex_for_pair(fullhash); assert(p->mutex); - p->value_rwlock.init(p->mutex); - nb_mutex_init(&p->disk_nb_mutex); + p->value_rwlock.init(p->mutex +#ifdef TOKU_MYSQL_WITH_PFS + , + *cachetable_value_key +#endif + ); + nb_mutex_init(*cachetable_disk_nb_mutex_key, + *cachetable_disk_nb_rwlock_key, + &p->disk_nb_mutex); - p->size_evicting_estimate = 0; // <CER> Is zero the correct init value? + p->size_evicting_estimate = 0; // <CER> Is zero the correct init value? p->ev = ev; p->list = list; @@ -3230,16 +3256,26 @@ void pair_list::init() { #if defined(HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP) pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); #else - // TODO: need to figure out how to make writer-preferential rwlocks - // happen on osx +// TODO: need to figure out how to make writer-preferential rwlocks +// happen on osx #endif - toku_pthread_rwlock_init(&m_list_lock, &attr); - toku_pthread_rwlock_init(&m_pending_lock_expensive, &attr); - toku_pthread_rwlock_init(&m_pending_lock_cheap, &attr); + toku_pthread_rwlock_init(*cachetable_m_list_lock_key, &m_list_lock, &attr); + toku_pthread_rwlock_init(*cachetable_m_pending_lock_expensive_key, + &m_pending_lock_expensive, + &attr); + toku_pthread_rwlock_init( + *cachetable_m_pending_lock_cheap_key, &m_pending_lock_cheap, &attr); XCALLOC_N(m_table_size, m_table); XCALLOC_N(m_num_locks, m_mutexes); for (uint64_t i = 0; i < m_num_locks; i++) { - toku_mutex_init(&m_mutexes[i].aligned_mutex, NULL); + toku_mutex_init( +#ifdef TOKU_PFS_MUTEX_EXTENDED_CACHETABLEMMUTEX + *cachetable_m_mutex_key, +#else + toku_uninstrumented, +#endif + &m_mutexes[i].aligned_mutex, + nullptr); } } @@ -3579,9 +3615,9 @@ ENSURE_POD(evictor); // This is the function that runs eviction on its own thread. // static void *eviction_thread(void *evictor_v) { - evictor* CAST_FROM_VOIDP(evictor, evictor_v); + evictor *CAST_FROM_VOIDP(evictor, evictor_v); evictor->run_eviction_thread(); - return evictor_v; + return toku_pthread_done(evictor_v); } // @@ -3630,11 +3666,14 @@ int evictor::init(long _size_limit, pair_list* _pl, cachefile_list* _cf_list, KI m_pl = _pl; m_cf_list = _cf_list; - m_kibbutz = _kibbutz; - toku_mutex_init(&m_ev_thread_lock, NULL); - toku_cond_init(&m_flow_control_cond, NULL); - toku_cond_init(&m_ev_thread_cond, NULL); - m_num_sleepers = 0; + m_kibbutz = _kibbutz; + toku_mutex_init( + *cachetable_ev_thread_lock_mutex_key, &m_ev_thread_lock, nullptr); + toku_cond_init( + *cachetable_m_flow_control_cond_key, &m_flow_control_cond, nullptr); + toku_cond_init( + *cachetable_m_ev_thread_cond_key, &m_ev_thread_cond, nullptr); + m_num_sleepers = 0; m_ev_thread_is_running = false; m_period_in_seconds = eviction_period; @@ -3642,11 +3681,12 @@ int evictor::init(long _size_limit, pair_list* _pl, cachefile_list* _cf_list, KI int r = myinitstate_r(seed, m_random_statebuf, sizeof m_random_statebuf, &m_random_data); assert_zero(r); - // start the background thread + // start the background thread m_run_thread = true; m_num_eviction_thread_runs = 0; m_ev_thread_init = false; - r = toku_pthread_create(&m_ev_thread, NULL, eviction_thread, this); + r = toku_pthread_create( + *eviction_thread_key, &m_ev_thread, nullptr, eviction_thread, this); if (r == 0) { m_ev_thread_init = true; } @@ -4703,7 +4743,7 @@ static_assert(std::is_pod<cachefile_list>::value, "cachefile_list isn't POD"); void cachefile_list::init() { m_next_filenum_to_use.fileid = 0; m_next_hash_id_to_use = 0; - toku_pthread_rwlock_init(&m_lock, NULL); + toku_pthread_rwlock_init(*cachetable_m_lock_key, &m_lock, nullptr); m_active_filenum.create(); m_active_fileid.create(); m_stale_fileid.create(); diff --git a/storage/tokudb/PerconaFT/ft/cachetable/checkpoint.cc b/storage/tokudb/PerconaFT/ft/cachetable/checkpoint.cc index 4d54962fe9c..aad018f4097 100644 --- a/storage/tokudb/PerconaFT/ft/cachetable/checkpoint.cc +++ b/storage/tokudb/PerconaFT/ft/cachetable/checkpoint.cc @@ -87,8 +87,16 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "util/frwlock.h" #include "util/status.h" -void -toku_checkpoint_get_status(CACHETABLE ct, CHECKPOINT_STATUS statp) { +toku_instr_key *checkpoint_safe_mutex_key; +toku_instr_key *checkpoint_safe_rwlock_key; +toku_instr_key *multi_operation_lock_key; +toku_instr_key *low_priority_multi_operation_lock_key; + +toku_instr_key *rwlock_cond_key; +toku_instr_key *rwlock_wait_read_key; +toku_instr_key *rwlock_wait_write_key; + +void toku_checkpoint_get_status(CACHETABLE ct, CHECKPOINT_STATUS statp) { cp_status.init(); CP_STATUS_VAL(CP_PERIOD) = toku_get_checkpoint_period_unlocked(ct); *statp = cp_status; @@ -117,11 +125,14 @@ multi_operation_lock_init(void) { #if defined(HAVE_PTHREAD_RWLOCKATTR_SETKIND_NP) pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); #else - // TODO: need to figure out how to make writer-preferential rwlocks - // happen on osx +// TODO: need to figure out how to make writer-preferential rwlocks +// happen on osx #endif - toku_pthread_rwlock_init(&multi_operation_lock, &attr); - toku_pthread_rwlock_init(&low_priority_multi_operation_lock, &attr); + toku_pthread_rwlock_init( + *multi_operation_lock_key, &multi_operation_lock, &attr); + toku_pthread_rwlock_init(*low_priority_multi_operation_lock_key, + &low_priority_multi_operation_lock, + &attr); pthread_rwlockattr_destroy(&attr); locked_mo = false; } @@ -146,10 +157,15 @@ multi_operation_checkpoint_unlock(void) { toku_pthread_rwlock_wrunlock(&low_priority_multi_operation_lock); } -static void -checkpoint_safe_lock_init(void) { - toku_mutex_init(&checkpoint_safe_mutex, NULL); - checkpoint_safe_lock.init(&checkpoint_safe_mutex); +static void checkpoint_safe_lock_init(void) { + toku_mutex_init( + *checkpoint_safe_mutex_key, &checkpoint_safe_mutex, nullptr); + checkpoint_safe_lock.init(&checkpoint_safe_mutex +#ifdef TOKU_MYSQL_WITH_PFS + , + *checkpoint_safe_rwlock_key +#endif + ); locked_cs = false; } diff --git a/storage/tokudb/PerconaFT/ft/ft-ops.cc b/storage/tokudb/PerconaFT/ft/ft-ops.cc index 20035b1d02f..ef2009db1b1 100644 --- a/storage/tokudb/PerconaFT/ft/ft-ops.cc +++ b/storage/tokudb/PerconaFT/ft/ft-ops.cc @@ -187,9 +187,35 @@ basement nodes, bulk fetch, and partial fetch: */ static toku_mutex_t ft_open_close_lock; - -void -toku_ft_get_status(FT_STATUS s) { +static toku_instr_key *ft_open_close_lock_mutex_key; +// FIXME: the instrumentation keys below are defined here even though they +// belong to other modules, because they are registered here. If desired, they +// can be moved to their proper modules and registration done there in a +// one-time init function +// locktree +toku_instr_key *treenode_mutex_key; +toku_instr_key *manager_mutex_key; +toku_instr_key *manager_escalation_mutex_key; +toku_instr_key *manager_escalator_mutex_key; +// src +toku_instr_key *db_txn_struct_i_txn_mutex_key; +toku_instr_key *indexer_i_indexer_lock_mutex_key; +toku_instr_key *indexer_i_indexer_estimate_lock_mutex_key; +toku_instr_key *result_i_open_dbs_rwlock_key; +// locktree +toku_instr_key *lock_request_m_wait_cond_key; +toku_instr_key *manager_m_escalator_done_key; +toku_instr_key *locktree_request_info_mutex_key; +toku_instr_key *locktree_request_info_retry_mutex_key; +toku_instr_key *locktree_request_info_retry_cv_key; + +// this is a sample probe for custom instrumentation +static toku_instr_key *fti_probe_1_key; + +// This is a sample probe for custom instrumentation +toku_instr_probe *toku_instr_probe_1; + +void toku_ft_get_status(FT_STATUS s) { ft_status.init(); *s = ft_status; @@ -2644,11 +2670,14 @@ void toku_ft_set_direct_io (bool direct_io_on) { use_direct_io = direct_io_on; } -static inline int ft_open_maybe_direct(const char *filename, int oflag, int mode) { +static inline int ft_open_maybe_direct(const char *filename, + int oflag, + int mode) { if (use_direct_io) { - return toku_os_open_direct(filename, oflag, mode); + return toku_os_open_direct( + filename, oflag, mode, *tokudb_file_data_key); } else { - return toku_os_open(filename, oflag, mode); + return toku_os_open(filename, oflag, mode, *tokudb_file_data_key); } } @@ -2722,7 +2751,7 @@ bool toku_create_subdirs_if_needed(const char *path) { if (!subdir.get()) return true; - if (toku_stat(subdir.get(), &stat) == -1) { + if (toku_stat(subdir.get(), &stat, toku_uninstrumented) == -1) { if (ENOENT == get_error_errno()) subdir_exists = false; else @@ -2934,6 +2963,8 @@ ft_handle_open(FT_HANDLE ft_h, const char *fname_in_env, int is_create, int only CACHEFILE cf = NULL; FT ft = NULL; bool did_create = false; + bool was_already_open = false; + toku_ft_open_close_lock(); if (ft_h->did_set_flags) { @@ -2945,7 +2976,6 @@ ft_handle_open(FT_HANDLE ft_h, const char *fname_in_env, int is_create, int only FILENUM reserved_filenum; reserved_filenum = use_filenum; fname_in_cwd = toku_cachetable_get_fname_in_cwd(cachetable, fname_in_env); - bool was_already_open; { int fd = -1; r = ft_open_file(fname_in_cwd, &fd); @@ -4615,20 +4645,265 @@ int toku_dump_ft(FILE *f, FT_HANDLE ft_handle) { return toku_dump_ftnode(f, ft_handle, root_key, 0, 0, 0); } + +static void toku_pfs_keys_init(const char *toku_instr_group_name) { + kibbutz_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, "kibbutz_mutex"); + minicron_p_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "minicron_p_mutex"); + queue_result_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "queue_result_mutex"); + tpool_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "tpool_lock_mutex"); + workset_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "workset_lock_mutex"); + bjm_jobs_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "bjm_jobs_lock_mutex"); + log_internal_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "log_internal_lock_mutex"); + cachetable_ev_thread_lock_mutex_key = + new toku_instr_key(toku_instr_object_type::mutex, + toku_instr_group_name, + "cachetable_ev_thread_lock_mutex"); + cachetable_disk_nb_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "cachetable_disk_nb_mutex"); + safe_file_size_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "safe_file_size_lock_mutex"); + cachetable_m_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "cachetable_m_mutex_key"); + checkpoint_safe_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "checkpoint_safe_mutex"); + ft_ref_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "ft_ref_lock_mutex"); + ft_open_close_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "ft_open_close_lock_mutex"); + loader_error_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "loader_error_mutex"); + bfs_mutex_key = + new toku_instr_key(toku_instr_object_type::mutex, toku_instr_group_name, + "bfs_mutex"); + loader_bl_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "loader_bl_mutex"); + loader_fi_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "loader_fi_lock_mutex"); + loader_out_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "loader_out_mutex"); + result_output_condition_lock_mutex_key = + new toku_instr_key(toku_instr_object_type::mutex, + toku_instr_group_name, + "result_output_condition_lock_mutex"); + block_table_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "block_table_mutex"); + rollback_log_node_cache_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "rollback_log_node_cache_mutex"); + txn_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, "txn_lock_mutex"); + txn_state_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "txn_state_lock_mutex"); + txn_child_manager_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "txn_child_manager_mutex"); + txn_manager_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "txn_manager_lock_mutex"); + treenode_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, "treenode_mutex"); + locktree_request_info_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "locktree_request_info_mutex"); + locktree_request_info_retry_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "locktree_request_info_retry_mutex_key"); + manager_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, "manager_mutex"); + manager_escalation_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "manager_escalation_mutex"); + db_txn_struct_i_txn_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "db_txn_struct_i_txn_mutex"); + manager_escalator_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "manager_escalator_mutex"); + indexer_i_indexer_lock_mutex_key = new toku_instr_key( + toku_instr_object_type::mutex, toku_instr_group_name, + "indexer_i_indexer_lock_mutex"); + indexer_i_indexer_estimate_lock_mutex_key = + new toku_instr_key(toku_instr_object_type::mutex, + toku_instr_group_name, + "indexer_i_indexer_estimate_lock_mutex"); + + tokudb_file_data_key = new toku_instr_key( + toku_instr_object_type::file, toku_instr_group_name, "tokudb_data_file"); + tokudb_file_load_key = new toku_instr_key( + toku_instr_object_type::file, toku_instr_group_name, "tokudb_load_file"); + tokudb_file_tmp_key = new toku_instr_key( + toku_instr_object_type::file, toku_instr_group_name, "tokudb_tmp_file"); + tokudb_file_log_key = new toku_instr_key( + toku_instr_object_type::file, toku_instr_group_name, "tokudb_log_file"); + + fti_probe_1_key = + new toku_instr_key(toku_instr_object_type::mutex, toku_instr_group_name, + "fti_probe_1"); + + extractor_thread_key = new toku_instr_key( + toku_instr_object_type::thread, toku_instr_group_name, + "extractor_thread"); + fractal_thread_key = new toku_instr_key( + toku_instr_object_type::thread, toku_instr_group_name, "fractal_thread"); + io_thread_key = + new toku_instr_key(toku_instr_object_type::thread, toku_instr_group_name, + "io_thread"); + eviction_thread_key = new toku_instr_key( + toku_instr_object_type::thread, toku_instr_group_name, + "eviction_thread"); + kibbutz_thread_key = new toku_instr_key( + toku_instr_object_type::thread, toku_instr_group_name, "kibbutz_thread"); + minicron_thread_key = new toku_instr_key( + toku_instr_object_type::thread, toku_instr_group_name, + "minicron_thread"); + tp_internal_thread_key = new toku_instr_key( + toku_instr_object_type::thread, toku_instr_group_name, + "tp_internal_thread"); + + result_state_cond_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "result_state_cond"); + bjm_jobs_wait_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, "bjm_jobs_wait"); + cachetable_p_refcount_wait_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "cachetable_p_refcount_wait"); + cachetable_m_flow_control_cond_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "cachetable_m_flow_control_cond"); + cachetable_m_ev_thread_cond_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "cachetable_m_ev_thread_cond"); + bfs_cond_key = + new toku_instr_key(toku_instr_object_type::cond, toku_instr_group_name, + "bfs_cond"); + result_output_condition_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "result_output_condition"); + manager_m_escalator_done_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "manager_m_escalator_done"); + lock_request_m_wait_cond_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "lock_request_m_wait_cond"); + queue_result_cond_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "queue_result_cond"); + ws_worker_wait_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, "ws_worker_wait"); + rwlock_wait_read_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, "rwlock_wait_read"); + rwlock_wait_write_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "rwlock_wait_write"); + rwlock_cond_key = + new toku_instr_key(toku_instr_object_type::cond, toku_instr_group_name, + "rwlock_cond"); + tp_thread_wait_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, "tp_thread_wait"); + tp_pool_wait_free_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "tp_pool_wait_free"); + frwlock_m_wait_read_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "frwlock_m_wait_read"); + kibbutz_k_cond_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, "kibbutz_k_cond"); + minicron_p_condvar_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "minicron_p_condvar"); + locktree_request_info_retry_cv_key = new toku_instr_key( + toku_instr_object_type::cond, toku_instr_group_name, + "locktree_request_info_retry_cv_key"); + + multi_operation_lock_key = new toku_instr_key( + toku_instr_object_type::rwlock, toku_instr_group_name, + "multi_operation_lock"); + low_priority_multi_operation_lock_key = + new toku_instr_key(toku_instr_object_type::rwlock, + toku_instr_group_name, + "low_priority_multi_operation_lock"); + cachetable_m_list_lock_key = new toku_instr_key( + toku_instr_object_type::rwlock, toku_instr_group_name, + "cachetable_m_list_lock"); + cachetable_m_pending_lock_expensive_key = + new toku_instr_key(toku_instr_object_type::rwlock, + toku_instr_group_name, + "cachetable_m_pending_lock_expensive"); + cachetable_m_pending_lock_cheap_key = + new toku_instr_key(toku_instr_object_type::rwlock, + toku_instr_group_name, + "cachetable_m_pending_lock_cheap"); + cachetable_m_lock_key = new toku_instr_key( + toku_instr_object_type::rwlock, toku_instr_group_name, + "cachetable_m_lock"); + result_i_open_dbs_rwlock_key = new toku_instr_key( + toku_instr_object_type::rwlock, toku_instr_group_name, + "result_i_open_dbs_rwlock"); + checkpoint_safe_rwlock_key = new toku_instr_key( + toku_instr_object_type::rwlock, toku_instr_group_name, + "checkpoint_safe_rwlock"); + cachetable_value_key = new toku_instr_key( + toku_instr_object_type::rwlock, toku_instr_group_name, + "cachetable_value"); + safe_file_size_lock_rwlock_key = new toku_instr_key( + toku_instr_object_type::rwlock, toku_instr_group_name, + "safe_file_size_lock_rwlock"); + cachetable_disk_nb_rwlock_key = new toku_instr_key( + toku_instr_object_type::rwlock, toku_instr_group_name, + "cachetable_disk_nb_rwlock"); + + toku_instr_probe_1 = new toku_instr_probe(*fti_probe_1_key); +} + int toku_ft_layer_init(void) { int r = 0; - //Portability must be initialized first + + // Portability must be initialized first r = toku_portability_init(); - if (r) { goto exit; } + if (r) { + goto exit; + } + + toku_pfs_keys_init("fti"); + r = db_env_set_toku_product_name("tokudb"); - if (r) { goto exit; } + if (r) { + goto exit; + } partitioned_counters_init(); toku_status_init(); toku_context_status_init(); toku_checkpoint_init(); toku_ft_serialize_layer_init(); - toku_mutex_init(&ft_open_close_lock, NULL); + toku_mutex_init( + *ft_open_close_lock_mutex_key, &ft_open_close_lock, nullptr); toku_scoped_malloc_init(); exit: return r; @@ -4642,7 +4917,10 @@ void toku_ft_layer_destroy(void) { toku_status_destroy(); partitioned_counters_destroy(); toku_scoped_malloc_destroy(); - //Portability must be cleaned up last + + delete toku_instr_probe_1; + + // Portability must be cleaned up last toku_portability_destroy(); } diff --git a/storage/tokudb/PerconaFT/ft/ft.cc b/storage/tokudb/PerconaFT/ft/ft.cc index abc9d295eae..c7c2ea33c9e 100644 --- a/storage/tokudb/PerconaFT/ft/ft.cc +++ b/storage/tokudb/PerconaFT/ft/ft.cc @@ -51,9 +51,10 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include <toku_assert.h> #include <portability/toku_atomic.h> -void -toku_reset_root_xid_that_created(FT ft, TXNID new_root_xid_that_created) { - // Reset the root_xid_that_created field to the given value. +toku_instr_key *ft_ref_lock_mutex_key; + +void toku_reset_root_xid_that_created(FT ft, TXNID new_root_xid_that_created) { + // Reset the root_xid_that_created field to the given value. // This redefines which xid created the dictionary. // hold lock around setting and clearing of dirty bit @@ -101,15 +102,11 @@ toku_ft_free (FT ft) { toku_free(ft); } -void -toku_ft_init_reflock(FT ft) { - toku_mutex_init(&ft->ft_ref_lock, NULL); +void toku_ft_init_reflock(FT ft) { + toku_mutex_init(*ft_ref_lock_mutex_key, &ft->ft_ref_lock, nullptr); } -void -toku_ft_destroy_reflock(FT ft) { - toku_mutex_destroy(&ft->ft_ref_lock); -} +void toku_ft_destroy_reflock(FT ft) { toku_mutex_destroy(&ft->ft_ref_lock); } void toku_ft_grab_reflock(FT ft) { diff --git a/storage/tokudb/PerconaFT/ft/loader/callbacks.cc b/storage/tokudb/PerconaFT/ft/loader/callbacks.cc index 6a520dba3a3..ac69fb7e789 100644 --- a/storage/tokudb/PerconaFT/ft/loader/callbacks.cc +++ b/storage/tokudb/PerconaFT/ft/loader/callbacks.cc @@ -45,6 +45,8 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "loader/loader-internal.h" #include "util/dbt.h" +toku_instr_key *loader_error_mutex_key; + static void error_callback_lock(ft_loader_error_callback loader_error) { toku_mutex_lock(&loader_error->mutex); } @@ -57,10 +59,10 @@ void ft_loader_init_error_callback(ft_loader_error_callback loader_error) { memset(loader_error, 0, sizeof *loader_error); toku_init_dbt(&loader_error->key); toku_init_dbt(&loader_error->val); - toku_mutex_init(&loader_error->mutex, NULL); + toku_mutex_init(*loader_error_mutex_key, &loader_error->mutex, nullptr); } -void ft_loader_destroy_error_callback(ft_loader_error_callback loader_error) { +void ft_loader_destroy_error_callback(ft_loader_error_callback loader_error) { toku_mutex_destroy(&loader_error->mutex); toku_destroy_dbt(&loader_error->key); toku_destroy_dbt(&loader_error->val); diff --git a/storage/tokudb/PerconaFT/ft/loader/dbufio.cc b/storage/tokudb/PerconaFT/ft/loader/dbufio.cc index ad084a4fbdc..90f76cecf90 100644 --- a/storage/tokudb/PerconaFT/ft/loader/dbufio.cc +++ b/storage/tokudb/PerconaFT/ft/loader/dbufio.cc @@ -49,6 +49,10 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "loader/dbufio.h" #include "loader/loader-internal.h" +toku_instr_key *bfs_mutex_key; +toku_instr_key *bfs_cond_key; +toku_instr_key *io_thread_key; + struct dbufio_file { // i/o thread owns these int fd; @@ -276,39 +280,44 @@ static void* io_thread (void *v) toku_mutex_lock(&bfs->mutex); //printf("%s:%d Locked\n", __FILE__, __LINE__); while (1) { + if (paniced(bfs)) { + toku_mutex_unlock(&bfs->mutex); // ignore any error + toku_instr_delete_current_thread(); + return toku_pthread_done(nullptr); + } + // printf("n_not_done=%d\n", bfs->n_not_done); + if (bfs->n_not_done == 0) { + // all done (meaning we stored EOF (or another error) in + // error_code[0] for the file. + // printf("unlocked\n"); + toku_mutex_unlock(&bfs->mutex); + toku_instr_delete_current_thread(); + return toku_pthread_done(nullptr); + } - if (paniced(bfs)) { - toku_mutex_unlock(&bfs->mutex); // ignore any error - return 0; - } - //printf("n_not_done=%d\n", bfs->n_not_done); - if (bfs->n_not_done==0) { - // all done (meaning we stored EOF (or another error) in error_code[0] for the file. - //printf("unlocked\n"); - toku_mutex_unlock(&bfs->mutex); - return 0; - } - - struct dbufio_file *dbf = bfs->head; - if (dbf==NULL) { - // No I/O needs to be done yet. - // Wait until something happens that will wake us up. - toku_cond_wait(&bfs->cond, &bfs->mutex); - if (paniced(bfs)) { - toku_mutex_unlock(&bfs->mutex); // ignore any error - return 0; - } - // Have the lock so go around. - } else { - // Some I/O needs to be done. - //printf("%s:%d Need I/O\n", __FILE__, __LINE__); - assert(dbf->second_buf_ready == false); - assert(!dbf->io_done); - bfs->head = dbf->next; - if (bfs->head==NULL) bfs->tail=NULL; - - // Unlock the mutex now that we have ownership of dbf to allow consumers to get the mutex and perform swaps. They won't swap - // this buffer because second_buf_ready is false. + struct dbufio_file *dbf = bfs->head; + if (dbf == NULL) { + // No I/O needs to be done yet. + // Wait until something happens that will wake us up. + toku_cond_wait(&bfs->cond, &bfs->mutex); + if (paniced(bfs)) { + toku_mutex_unlock(&bfs->mutex); // ignore any error + toku_instr_delete_current_thread(); + return toku_pthread_done(nullptr); + } + // Have the lock so go around. + } else { + // Some I/O needs to be done. + // printf("%s:%d Need I/O\n", __FILE__, __LINE__); + assert(dbf->second_buf_ready == false); + assert(!dbf->io_done); + bfs->head = dbf->next; + if (bfs->head == NULL) + bfs->tail = NULL; + + // Unlock the mutex now that we have ownership of dbf to allow + // consumers to get the mutex and perform swaps. They won't swap + // this buffer because second_buf_ready is false. toku_mutex_unlock(&bfs->mutex); //printf("%s:%d Doing read fd=%d\n", __FILE__, __LINE__, dbf->fd); { @@ -339,14 +348,16 @@ static void* io_thread (void *v) //printf("%s:%d locking mutex again=%ld\n", __FILE__, __LINE__, readcode); { - toku_mutex_lock(&bfs->mutex); - if (paniced(bfs)) { - toku_mutex_unlock(&bfs->mutex); // ignore any error - return 0; - } - } - // Now that we have the mutex, we can decrement n_not_done (if applicable) and set second_buf_ready - if (readcode<=0) { + toku_mutex_lock(&bfs->mutex); + if (paniced(bfs)) { + toku_mutex_unlock(&bfs->mutex); // ignore any error + toku_instr_delete_current_thread(); + return toku_pthread_done(nullptr); + } + } + // Now that we have the mutex, we can decrement n_not_done (if + // applicable) and set second_buf_ready + if (readcode<=0) { bfs->n_not_done--; } //printf("%s:%d n_not_done=%d\n", __FILE__, __LINE__, bfs->n_not_done); @@ -377,34 +388,36 @@ int create_dbufio_fileset (DBUFIO_FILESET *bfsp, int N, int fds[/*N*/], size_t b } } } - //printf("%s:%d here\n", __FILE__, __LINE__); - if (result==0) { - toku_mutex_init(&bfs->mutex, NULL); - mutex_inited = true; + // printf("%s:%d here\n", __FILE__, __LINE__); + if (result == 0) { + toku_mutex_init(*bfs_mutex_key, &bfs->mutex, nullptr); + mutex_inited = true; } - if (result==0) { - toku_cond_init(&bfs->cond, NULL); - cond_inited = true; + if (result == 0) { + toku_cond_init(*bfs_cond_key, &bfs->cond, nullptr); + cond_inited = true; } - if (result==0) { - bfs->N = N; - bfs->n_not_done = N; - bfs->head = bfs->tail = NULL; - for (int i=0; i<N; i++) { - bfs->files[i].fd = fds[i]; - bfs->files[i].offset_in_buf = 0; - bfs->files[i].offset_in_uncompressed_file = 0; - bfs->files[i].next = NULL; - bfs->files[i].second_buf_ready = false; - for (int j=0; j<2; j++) { - if (result==0) { - MALLOC_N(bufsize, bfs->files[i].buf[j]); - if (bfs->files[i].buf[j]==NULL) { result=get_error_errno(); } - } - bfs->files[i].n_in_buf[j] = 0; - bfs->files[i].error_code[j] = 0; - } - bfs->files[i].io_done = false; + if (result == 0) { + bfs->N = N; + bfs->n_not_done = N; + bfs->head = bfs->tail = NULL; + for (int i = 0; i < N; i++) { + bfs->files[i].fd = fds[i]; + bfs->files[i].offset_in_buf = 0; + bfs->files[i].offset_in_uncompressed_file = 0; + bfs->files[i].next = NULL; + bfs->files[i].second_buf_ready = false; + for (int j = 0; j < 2; j++) { + if (result == 0) { + MALLOC_N(bufsize, bfs->files[i].buf[j]); + if (bfs->files[i].buf[j] == NULL) { + result = get_error_errno(); + } + } + bfs->files[i].n_in_buf[j] = 0; + bfs->files[i].error_code[j] = 0; + } + bfs->files[i].io_done = false; ssize_t r; if (bfs->compressed) { r = dbf_read_compressed(&bfs->files[i], bfs->files[i].buf[0], bufsize); @@ -431,13 +444,21 @@ int create_dbufio_fileset (DBUFIO_FILESET *bfsp, int N, int fds[/*N*/], size_t b bfs->panic = false; bfs->panic_errno = 0; } - //printf("Creating IO thread\n"); - if (result==0) { - result = toku_pthread_create(&bfs->iothread, NULL, io_thread, (void*)bfs); + // printf("Creating IO thread\n"); + if (result == 0) { + result = toku_pthread_create(*io_thread_key, + &bfs->iothread, + nullptr, + io_thread, + static_cast<void *>(bfs)); + } + if (result == 0) { + *bfsp = bfs; + return 0; } - if (result==0) { *bfsp = bfs; return 0; } // Now undo everything. - // If we got here, there is no thread (either result was zero before the thread was created, or else the thread creation itself failed. + // If we got here, there is no thread (either result was zero before the + // thread was created, or else the thread creation itself failed. if (bfs) { if (bfs->files) { // the files were allocated, so we have to free all the bufs. diff --git a/storage/tokudb/PerconaFT/ft/loader/loader-internal.h b/storage/tokudb/PerconaFT/ft/loader/loader-internal.h index 1aa2c203831..6f7b0147b21 100644 --- a/storage/tokudb/PerconaFT/ft/loader/loader-internal.h +++ b/storage/tokudb/PerconaFT/ft/loader/loader-internal.h @@ -64,10 +64,10 @@ enum { /* These structures maintain a collection of all the open temporary files used by the loader. */ struct file_info { bool is_open; - bool is_extant; // if true, the file must be unlinked. + bool is_extant; // if true, the file must be unlinked. char *fname; - FILE *file; - uint64_t n_rows; // how many rows were written into that file + TOKU_FILE *file; + uint64_t n_rows; // how many rows were written into that file size_t buffer_size; void *buffer; }; @@ -80,11 +80,11 @@ struct file_infos { }; typedef struct fidx { int idx; } FIDX; static const FIDX FIDX_NULL __attribute__((__unused__)) = {-1}; -static int fidx_is_null (const FIDX f) __attribute__((__unused__)); -static int fidx_is_null (const FIDX f) { return f.idx==-1; } -FILE *toku_bl_fidx2file (FTLOADER bl, FIDX i); +static int fidx_is_null(const FIDX f) __attribute__((__unused__)); +static int fidx_is_null(const FIDX f) { return f.idx == -1; } +TOKU_FILE *toku_bl_fidx2file(FTLOADER bl, FIDX i); -int ft_loader_open_temp_file (FTLOADER bl, FIDX*file_idx); +int ft_loader_open_temp_file(FTLOADER bl, FIDX *file_idx); /* These data structures are used for manipulating a collection of rows in main memory. */ struct row { @@ -100,11 +100,17 @@ struct rowset { }; int init_rowset (struct rowset *rows, uint64_t memory_budget); -void destroy_rowset (struct rowset *rows); -int add_row (struct rowset *rows, DBT *key, DBT *val); - -int loader_write_row(DBT *key, DBT *val, FIDX data, FILE*, uint64_t *dataoff, struct wbuf *wb, FTLOADER bl); -int loader_read_row (FILE *f, DBT *key, DBT *val); +void destroy_rowset(struct rowset *rows); +int add_row(struct rowset *rows, DBT *key, DBT *val); + +int loader_write_row(DBT *key, + DBT *val, + FIDX data, + TOKU_FILE *, + uint64_t *dataoff, + struct wbuf *wb, + FTLOADER bl); +int loader_read_row(TOKU_FILE *f, DBT *key, DBT *val); struct merge_fileset { bool have_sorted_output; // Is there an previous key? @@ -195,12 +201,13 @@ struct ft_loader_s { bool did_reserve_memory; bool compress_intermediates; bool allow_puts; - uint64_t reserved_memory; // how much memory are we allowed to use? + uint64_t reserved_memory; // how much memory are we allowed to use? - /* To make it easier to recover from errors, we don't use FILE*, instead we use an index into the file_infos. */ + /* To make it easier to recover from errors, we don't use TOKU_FILE*, + * instead we use an index into the file_infos. */ struct file_infos file_infos; -#define PROGRESS_MAX (1<<16) +#define PROGRESS_MAX (1 << 16) int progress; // Progress runs from 0 to PROGRESS_MAX. When we call the poll function we convert to a float from 0.0 to 1.0 // We use an integer so that we can add to the progress using a fetch-and-add instruction. diff --git a/storage/tokudb/PerconaFT/ft/loader/loader.cc b/storage/tokudb/PerconaFT/ft/loader/loader.cc index f867639b953..5f57b473bc5 100644 --- a/storage/tokudb/PerconaFT/ft/loader/loader.cc +++ b/storage/tokudb/PerconaFT/ft/loader/loader.cc @@ -63,21 +63,17 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "util/x1764.h" -static size_t (*os_fwrite_fun)(const void *,size_t,size_t,FILE*)=NULL; -void ft_loader_set_os_fwrite (size_t (*fwrite_fun)(const void*,size_t,size_t,FILE*)) { - os_fwrite_fun=fwrite_fun; -} +toku_instr_key *loader_bl_mutex_key; +toku_instr_key *loader_fi_lock_mutex_key; +toku_instr_key *loader_out_mutex_key; -static size_t do_fwrite (const void *ptr, size_t size, size_t nmemb, FILE *stream) { - if (os_fwrite_fun) { - return os_fwrite_fun(ptr, size, nmemb, stream); - } else { - return fwrite(ptr, size, nmemb, stream); - } -} +toku_instr_key *extractor_thread_key; +toku_instr_key *fractal_thread_key; +toku_instr_key *tokudb_file_tmp_key; +toku_instr_key *tokudb_file_load_key; -// 1024 is the right size_factor for production. +// 1024 is the right size_factor for production. // Different values for these sizes may be used for testing. static uint32_t size_factor = 1024; static uint32_t default_loader_nodesize = FT_DEFAULT_NODE_SIZE; @@ -99,7 +95,7 @@ toku_ft_loader_get_rowset_budget_for_testing (void) void ft_loader_lock_init(FTLOADER bl) { invariant(!bl->mutex_init); - toku_mutex_init(&bl->mutex, NULL); + toku_mutex_init(*loader_bl_mutex_key, &bl->mutex, nullptr); bl->mutex_init = true; } @@ -131,7 +127,10 @@ static int add_big_buffer(struct file_info *file) { newbuffer = true; } if (result == 0) { - int r = setvbuf(file->file, (char *) file->buffer, _IOFBF, file->buffer_size); + int r = setvbuf(file->file->file, + static_cast<char *>(file->buffer), + _IOFBF, + file->buffer_size); if (r != 0) { result = get_error_errno(); if (newbuffer) { @@ -150,9 +149,9 @@ static void cleanup_big_buffer(struct file_info *file) { } } -int ft_loader_init_file_infos (struct file_infos *fi) { +int ft_loader_init_file_infos(struct file_infos *fi) { int result = 0; - toku_mutex_init(&fi->lock, NULL); + toku_mutex_init(*loader_fi_lock_mutex_key, &fi->lock, nullptr); fi->n_files = 0; fi->n_files_limit = 1; fi->n_files_open = 0; @@ -196,11 +195,10 @@ void ft_loader_fi_destroy (struct file_infos *fi, bool is_error) fi->file_infos = NULL; } -static int open_file_add (struct file_infos *fi, - FILE *file, - char *fname, - /* out */ FIDX *idx) -{ +static int open_file_add(struct file_infos *fi, + TOKU_FILE *file, + char *fname, + /* out */ FIDX *idx) { int result = 0; toku_mutex_lock(&fi->lock); if (fi->n_files >= fi->n_files_limit) { @@ -230,11 +228,12 @@ int ft_loader_fi_reopen (struct file_infos *fi, FIDX idx, const char *mode) { int result = 0; toku_mutex_lock(&fi->lock); int i = idx.idx; - invariant(i>=0 && i<fi->n_files); + invariant(i >= 0 && i < fi->n_files); invariant(!fi->file_infos[i].is_open); invariant(fi->file_infos[i].is_extant); - fi->file_infos[i].file = toku_os_fopen(fi->file_infos[i].fname, mode); - if (fi->file_infos[i].file == NULL) { + fi->file_infos[i].file = + toku_os_fopen(fi->file_infos[i].fname, mode, *tokudb_file_load_key); + if (fi->file_infos[i].file == NULL) { result = get_error_errno(); } else { fi->file_infos[i].is_open = true; @@ -307,20 +306,20 @@ int ft_loader_open_temp_file (FTLOADER bl, FIDX *file_idx) */ { int result = 0; - if (result) // debug hack + if (result) // debug hack return result; - FILE *f = NULL; + TOKU_FILE *f = NULL; int fd = -1; - char *fname = toku_strdup(bl->temp_file_template); + char *fname = toku_strdup(bl->temp_file_template); if (fname == NULL) result = get_error_errno(); else { fd = mkstemp(fname); - if (fd < 0) { + if (fd < 0) { result = get_error_errno(); } else { - f = toku_os_fdopen(fd, "r+"); - if (f == NULL) + f = toku_os_fdopen(fd, "r+", fname, *tokudb_file_tmp_key); + if (f->file == nullptr) result = get_error_errno(); else result = open_file_add(&bl->file_infos, f, fname, file_idx); @@ -339,7 +338,7 @@ int ft_loader_open_temp_file (FTLOADER bl, FIDX *file_idx) return result; } -void toku_ft_loader_internal_destroy (FTLOADER bl, bool is_error) { +void toku_ft_loader_internal_destroy(FTLOADER bl, bool is_error) { ft_loader_lock_destroy(bl); // These frees rely on the fact that if you free a NULL pointer then nothing bad happens. @@ -635,12 +634,16 @@ int toku_ft_loader_open (FTLOADER *blp, /* out */ allow_puts); if (r!=0) result = r; } - if (result==0 && allow_puts) { + if (result == 0 && allow_puts) { FTLOADER bl = *blp; - int r = toku_pthread_create(&bl->extractor_thread, NULL, extractor_thread, (void*)bl); - if (r==0) { + int r = toku_pthread_create(*extractor_thread_key, + &bl->extractor_thread, + nullptr, + extractor_thread, + static_cast<void *>(bl)); + if (r == 0) { bl->extractor_live = true; - } else { + } else { result = r; (void) toku_ft_loader_internal_destroy(bl, true); } @@ -659,17 +662,17 @@ static void ft_loader_set_panic(FTLOADER bl, int error, bool callback, int which } // One of the tests uses this. -FILE *toku_bl_fidx2file (FTLOADER bl, FIDX i) { +TOKU_FILE *toku_bl_fidx2file(FTLOADER bl, FIDX i) { toku_mutex_lock(&bl->file_infos.lock); - invariant(i.idx >=0 && i.idx < bl->file_infos.n_files); + invariant(i.idx >= 0 && i.idx < bl->file_infos.n_files); invariant(bl->file_infos.file_infos[i.idx].is_open); - FILE *result=bl->file_infos.file_infos[i.idx].file; + TOKU_FILE *result = bl->file_infos.file_infos[i.idx].file; toku_mutex_unlock(&bl->file_infos.lock); return result; } -static int bl_finish_compressed_write(FILE *stream, struct wbuf *wb) { - int r; +static int bl_finish_compressed_write(TOKU_FILE *stream, struct wbuf *wb) { + int r = 0; char *compressed_buf = NULL; const size_t data_size = wb->ndone; invariant(data_size > 0); @@ -720,31 +723,23 @@ static int bl_finish_compressed_write(FILE *stream, struct wbuf *wb) { // Mark as written wb->ndone = 0; - size_t size_to_write = total_size + 4; // Includes writing total_size + size_t size_to_write = total_size + 4; // Includes writing total_size + + r = toku_os_fwrite(compressed_buf, 1, size_to_write, stream); - { - size_t written = do_fwrite(compressed_buf, 1, size_to_write, stream); - if (written!=size_to_write) { - if (os_fwrite_fun) // if using hook to induce artificial errors (for testing) ... - r = get_maybe_error_errno(); // ... then there is no error in the stream, but there is one in errno - else - r = ferror(stream); - invariant(r!=0); - goto exit; - } - } - r = 0; -exit: if (compressed_buf) { toku_free(compressed_buf); } return r; } -static int bl_compressed_write(void *ptr, size_t nbytes, FILE *stream, struct wbuf *wb) { +static int bl_compressed_write(void *ptr, + size_t nbytes, + TOKU_FILE *stream, + struct wbuf *wb) { invariant(wb->size <= MAX_UNCOMPRESSED_BUF); size_t bytes_left = nbytes; - char *buf = (char*)ptr; + char *buf = (char *)ptr; while (bytes_left > 0) { size_t bytes_to_copy = bytes_left; @@ -767,29 +762,28 @@ static int bl_compressed_write(void *ptr, size_t nbytes, FILE *stream, struct wb return 0; } -static int bl_fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream, struct wbuf *wb, FTLOADER bl) -/* Effect: this is a wrapper for fwrite that returns 0 on success, otherwise returns an error number. +static int bl_fwrite(void *ptr, + size_t size, + size_t nmemb, + TOKU_FILE *stream, + struct wbuf *wb, + FTLOADER bl) +/* Effect: this is a wrapper for fwrite that returns 0 on success, otherwise + * returns an error number. * Arguments: * ptr the data to be writen. * size the amount of data to be written. * nmemb the number of units of size to be written. * stream write the data here. - * wb where to write uncompressed data (if we're compressing) or ignore if NULL - * bl passed so we can panic the ft_loader if something goes wrong (recording the error number). + * wb where to write uncompressed data (if we're compressing) or ignore if + * NULL + * bl passed so we can panic the ft_loader if something goes wrong + * (recording the error number). * Return value: 0 on success, an error number otherwise. */ { if (!bl->compress_intermediates || !wb) { - size_t r = do_fwrite(ptr, size, nmemb, stream); - if (r!=nmemb) { - int e; - if (os_fwrite_fun) // if using hook to induce artificial errors (for testing) ... - e = get_maybe_error_errno(); // ... then there is no error in the stream, but there is one in errno - else - e = ferror(stream); - invariant(e!=0); - return e; - } + return toku_os_fwrite(ptr, size, nmemb, stream); } else { size_t num_bytes = size * nmemb; int r = bl_compressed_write(ptr, num_bytes, stream, wb); @@ -800,8 +794,9 @@ static int bl_fwrite(void *ptr, size_t size, size_t nmemb, FILE *stream, struct return 0; } -static int bl_fread (void *ptr, size_t size, size_t nmemb, FILE *stream) -/* Effect: this is a wrapper for fread that returns 0 on success, otherwise returns an error number. +static int bl_fread(void *ptr, size_t size, size_t nmemb, TOKU_FILE *stream) +/* Effect: this is a wrapper for fread that returns 0 on success, otherwise + * returns an error number. * Arguments: * ptr read data into here. * size size of data element to be read. @@ -810,24 +805,14 @@ static int bl_fread (void *ptr, size_t size, size_t nmemb, FILE *stream) * Return value: 0 on success, an error number otherwise. */ { - size_t r = fread(ptr, size, nmemb, stream); - if (r==0) { - if (feof(stream)) return EOF; - else { - do_error: ; - int e = ferror(stream); - // r == 0 && !feof && e == 0, how does this happen? invariant(e!=0); - return e; - } - } else if (r<nmemb) { - goto do_error; - } else { - return 0; - } + return toku_os_fread(ptr, size, nmemb, stream); } -static int bl_write_dbt (DBT *dbt, FILE* datafile, uint64_t *dataoff, struct wbuf *wb, FTLOADER bl) -{ +static int bl_write_dbt(DBT *dbt, + TOKU_FILE *datafile, + uint64_t *dataoff, + struct wbuf *wb, + FTLOADER bl) { int r; int dlen = dbt->size; if ((r=bl_fwrite(&dlen, sizeof(dlen), 1, datafile, wb, bl))) return r; @@ -837,8 +822,7 @@ static int bl_write_dbt (DBT *dbt, FILE* datafile, uint64_t *dataoff, struct wbu return 0; } -static int bl_read_dbt (/*in*/DBT *dbt, FILE *stream) -{ +static int bl_read_dbt(/*in*/ DBT *dbt, TOKU_FILE *stream) { int len; { int r; @@ -892,13 +876,20 @@ static int bl_read_dbt_from_dbufio (/*in*/DBT *dbt, DBUFIO_FILESET bfs, int file return result; } - -int loader_write_row(DBT *key, DBT *val, FIDX data, FILE *dataf, uint64_t *dataoff, struct wbuf *wb, FTLOADER bl) -/* Effect: Given a key and a val (both DBTs), write them to a file. Increment *dataoff so that it's up to date. +int loader_write_row(DBT *key, + DBT *val, + FIDX data, + TOKU_FILE *dataf, + uint64_t *dataoff, + struct wbuf *wb, + FTLOADER bl) +/* Effect: Given a key and a val (both DBTs), write them to a file. Increment + * *dataoff so that it's up to date. * Arguments: * key, val write these. * data the file to write them to - * dataoff a pointer to a counter that keeps track of the amount of data written so far. + * dataoff a pointer to a counter that keeps track of the amount of data + * written so far. * wb a pointer (possibly NULL) to buffer uncompressed output * bl the ft_loader (passed so we can panic if needed). * Return value: 0 on success, an error number otherwise. @@ -916,8 +907,9 @@ int loader_write_row(DBT *key, DBT *val, FIDX data, FILE *dataf, uint64_t *datao return 0; } -int loader_read_row (FILE *f, DBT *key, DBT *val) -/* Effect: Read a key value pair from a file. The DBTs must have DB_DBT_REALLOC set. +int loader_read_row(TOKU_FILE *f, DBT *key, DBT *val) +/* Effect: Read a key value pair from a file. The DBTs must have DB_DBT_REALLOC + * set. * Arguments: * f where to read it from. * key, val read it into these. @@ -1087,7 +1079,7 @@ static void* extractor_thread (void *blv) { FTLOADER bl = (FTLOADER)blv; int r = 0; while (1) { - void *item; + void *item = nullptr; { int rq = toku_queue_deq(bl->primary_rowset_queue, &item, NULL, NULL); if (rq==EOF) break; @@ -1108,14 +1100,14 @@ static void* extractor_thread (void *blv) { //printf("%s:%d extractor finishing\n", __FILE__, __LINE__); if (r == 0) { r = finish_primary_rows(bl); - if (r) + if (r) ft_loader_set_panic(bl, r, false, 0, nullptr, nullptr); - } - return NULL; + toku_instr_delete_current_thread(); + return nullptr; } -static void enqueue_for_extraction (FTLOADER bl) { +static void enqueue_for_extraction(FTLOADER bl) { //printf("%s:%d enqueing %ld items\n", __FILE__, __LINE__, bl->primary_rowset.n_rows); struct rowset *XMALLOC(enqueue_me); *enqueue_me = bl->primary_rowset; @@ -1626,11 +1618,12 @@ static int write_rowset_to_file (FTLOADER bl, FIDX sfile, const struct rowset ro struct wbuf wb; wbuf_init(&wb, uncompressed_buffer, MAX_UNCOMPRESSED_BUF); - FILE *sstream = toku_bl_fidx2file(bl, sfile); - for (size_t i=0; i<rows.n_rows; i++) { - DBT skey = make_dbt(rows.data + rows.rows[i].off, rows.rows[i].klen); - DBT sval = make_dbt(rows.data + rows.rows[i].off + rows.rows[i].klen, rows.rows[i].vlen); - + TOKU_FILE *sstream = toku_bl_fidx2file(bl, sfile); + for (size_t i = 0; i < rows.n_rows; i++) { + DBT skey = make_dbt(rows.data + rows.rows[i].off, rows.rows[i].klen); + DBT sval = make_dbt(rows.data + rows.rows[i].off + rows.rows[i].klen, + rows.rows[i].vlen); + uint64_t soffset=0; // don't really need this. r = loader_write_row(&skey, &sval, sfile, sstream, &soffset, &wb, bl); if (r != 0) { @@ -1727,14 +1720,30 @@ int ft_loader_sort_and_write_rows (struct rowset *rows, struct merge_fileset *fs return sort_and_write_rows (*rows, fs, bl, which_db, dest_db, compare); } -int toku_merge_some_files_using_dbufio (const bool to_q, FIDX dest_data, QUEUE q, int n_sources, DBUFIO_FILESET bfs, FIDX srcs_fidxs[/*n_sources*/], FTLOADER bl, int which_db, DB *dest_db, ft_compare_func compare, int progress_allocation) -/* Effect: Given an array of FILE*'s each containing sorted, merge the data and write it to an output. All the files remain open after the merge. - * This merge is performed in one pass, so don't pass too many files in. If you need a tree of merges do it elsewhere. - * If TO_Q is true then we write rowsets into queue Q. Otherwise we write into dest_data. - * Modifies: May modify the arrays of files (but if modified, it must be a permutation so the caller can use that array to close everything.) - * Requires: The number of sources is at least one, and each of the input files must have at least one row in it. +int toku_merge_some_files_using_dbufio(const bool to_q, + FIDX dest_data, + QUEUE q, + int n_sources, + DBUFIO_FILESET bfs, + FIDX srcs_fidxs[/*n_sources*/], + FTLOADER bl, + int which_db, + DB *dest_db, + ft_compare_func compare, + int progress_allocation) +/* Effect: Given an array of FILE*'s each containing sorted, merge the data and + * write it to an output. All the files remain open after the merge. + * This merge is performed in one pass, so don't pass too many files in. If + * you need a tree of merges do it elsewhere. + * If TO_Q is true then we write rowsets into queue Q. Otherwise we write + * into dest_data. + * Modifies: May modify the arrays of files (but if modified, it must be a + * permutation so the caller can use that array to close everything.) + * Requires: The number of sources is at least one, and each of the input files + * must have at least one row in it. * Arguments: - * to_q boolean indicating that output is queue (true) or a file (false) + * to_q boolean indicating that output is queue (true) or a file + * (false) * dest_data where to write the sorted data * q where to write the sorted data * n_sources how many source files. @@ -1747,9 +1756,10 @@ int toku_merge_some_files_using_dbufio (const bool to_q, FIDX dest_data, QUEUE q { int result = 0; - FILE *dest_stream = to_q ? NULL : toku_bl_fidx2file(bl, dest_data); + TOKU_FILE *dest_stream = to_q ? nullptr : toku_bl_fidx2file(bl, dest_data); - //printf(" merge_some_files progress=%d fin at %d\n", bl->progress, bl->progress+progress_allocation); + // printf(" merge_some_files progress=%d fin at %d\n", bl->progress, + // bl->progress+progress_allocation); DBT keys[n_sources]; DBT vals[n_sources]; uint64_t dataoff[n_sources]; @@ -1943,12 +1953,18 @@ static int merge_some_files (const bool to_q, FIDX dest_data, QUEUE q, int n_sou int result = 0; DBUFIO_FILESET bfs = NULL; int *MALLOC_N(n_sources, fds); - if (fds==NULL) result=get_error_errno(); - if (result==0) { - for (int i=0; i<n_sources; i++) { - int r = fileno(toku_bl_fidx2file(bl, srcs_fidxs[i])); // we rely on the fact that when the files are closed, the fd is also closed. - if (r==-1) { - result=get_error_errno(); + if (fds == NULL) + result = get_error_errno(); + if (result == 0) { + for (int i = 0; i < n_sources; i++) { + int r = fileno( + toku_bl_fidx2file(bl, srcs_fidxs[i])->file); // we rely on the + // fact that when + // the files are + // closed, the fd + // is also closed. + if (r == -1) { + result = get_error_errno(); break; } fds[i] = r; @@ -2178,7 +2194,7 @@ static inline void dbout_init(struct dbout *out, FT ft) { out->current_off = 0; out->n_translations = out->n_translations_limit = 0; out->translation = NULL; - toku_mutex_init(&out->mutex, NULL); + toku_mutex_init(*loader_out_mutex_key, &out->mutex, nullptr); out->ft = ft; } @@ -2418,7 +2434,7 @@ static int toku_loader_write_ft_from_q (FTLOADER bl, assert_zero(r); return result; } - FILE *pivots_stream = toku_bl_fidx2file(bl, pivots_file); + TOKU_FILE *pivots_stream = toku_bl_fidx2file(bl, pivots_file); TXNID root_xid_that_created = TXNID_NONE; if (bl->root_xids_that_created) @@ -2705,21 +2721,35 @@ int toku_loader_write_ft_from_q_in_C (FTLOADER bl, static void* fractal_thread (void *ftav) { struct fractal_thread_args *fta = (struct fractal_thread_args *)ftav; - int r = toku_loader_write_ft_from_q (fta->bl, fta->descriptor, fta->fd, fta->progress_allocation, fta->q, fta->total_disksize_estimate, fta->which_db, fta->target_nodesize, fta->target_basementnodesize, fta->target_compression_method, fta->target_fanout); + int r = toku_loader_write_ft_from_q(fta->bl, + fta->descriptor, + fta->fd, + fta->progress_allocation, + fta->q, + fta->total_disksize_estimate, + fta->which_db, + fta->target_nodesize, + fta->target_basementnodesize, + fta->target_compression_method, + fta->target_fanout); fta->errno_result = r; - return NULL; -} - -static int loader_do_i (FTLOADER bl, - int which_db, - DB *dest_db, - ft_compare_func compare, - const DESCRIPTOR descriptor, - const char *new_fname, - int progress_allocation // how much progress do I need to add into bl->progress by the end.. - ) + toku_instr_delete_current_thread(); + return toku_pthread_done(nullptr); +} + +static int loader_do_i(FTLOADER bl, + int which_db, + DB *dest_db, + ft_compare_func compare, + const DESCRIPTOR descriptor, + const char *new_fname, + int progress_allocation // how much progress do I need + // to add into bl->progress by + // the end.. + ) /* Effect: Handle the file creating for one particular DB in the bulk loader. */ -/* Requires: The data is fully extracted, so we can do merges out of files and write the ft file. */ +/* Requires: The data is fully extracted, so we can do merges out of files and + write the ft file. */ { //printf("doing i use %d progress=%d fin at %d\n", progress_allocation, bl->progress, bl->progress+progress_allocation); struct merge_fileset *fs = &(bl->fs[which_db]); @@ -2730,10 +2760,14 @@ static int loader_do_i (FTLOADER bl, if (r) goto error; { - mode_t mode = S_IRUSR+S_IWUSR + S_IRGRP+S_IWGRP; - int fd = toku_os_open(new_fname, O_RDWR| O_CREAT | O_BINARY, mode); // #2621 + mode_t mode = S_IRUSR + S_IWUSR + S_IRGRP + S_IWGRP; + int fd = toku_os_open(new_fname, + O_RDWR | O_CREAT | O_BINARY, + mode, + *tokudb_file_load_key); // #2621 if (fd < 0) { - r = get_error_errno(); goto error; + r = get_error_errno(); + goto error; } uint32_t target_nodesize, target_basementnodesize, target_fanout; @@ -2753,24 +2787,27 @@ static int loader_do_i (FTLOADER bl, progress_allocation -= allocation_for_merge; // This structure must stay live until the join below. - struct fractal_thread_args fta = { - bl, - descriptor, - fd, - progress_allocation, - bl->fractal_queues[which_db], - bl->extracted_datasizes[which_db], - 0, - which_db, - target_nodesize, - target_basementnodesize, - target_compression_method, - target_fanout - }; - - r = toku_pthread_create(bl->fractal_threads+which_db, NULL, fractal_thread, (void*)&fta); + struct fractal_thread_args fta = {bl, + descriptor, + fd, + progress_allocation, + bl->fractal_queues[which_db], + bl->extracted_datasizes[which_db], + 0, + which_db, + target_nodesize, + target_basementnodesize, + target_compression_method, + target_fanout}; + + r = toku_pthread_create(*fractal_thread_key, + bl->fractal_threads + which_db, + nullptr, + fractal_thread, + static_cast<void *>(&fta)); if (r) { - int r2 __attribute__((__unused__)) = toku_queue_destroy(bl->fractal_queues[which_db]); + int r2 __attribute__((__unused__)) = + toku_queue_destroy(bl->fractal_queues[which_db]); // ignore r2, since we already have an error bl->fractal_queues[which_db] = nullptr; goto error; @@ -3107,7 +3144,7 @@ static int read_some_pivots (FIDX pivots_file, int n_to_read, FTLOADER bl, for (int i = 0; i < n_to_read; i++) pivots[i] = zero_dbt; - FILE *pivots_stream = toku_bl_fidx2file(bl, pivots_file); + TOKU_FILE *pivots_stream = toku_bl_fidx2file(bl, pivots_file); int result = 0; for (int i = 0; i < n_to_read; i++) { @@ -3159,8 +3196,9 @@ static int setup_nonleaf_block (int n_children, } if (result == 0) { - FILE *next_pivots_stream = toku_bl_fidx2file(bl, next_pivots_file); - int r = bl_write_dbt(&pivots[n_children-1], next_pivots_stream, NULL, nullptr, bl); + TOKU_FILE *next_pivots_stream = toku_bl_fidx2file(bl, next_pivots_file); + int r = bl_write_dbt( + &pivots[n_children - 1], next_pivots_stream, NULL, nullptr, bl); if (r) result = r; } @@ -3275,8 +3313,11 @@ static int write_nonleaves (FTLOADER bl, FIDX pivots_fidx, struct dbout *out, st // 2) We put the 15 pivots and 16 blocks into an non-leaf node. // 3) We put the 16th pivot into the next pivots file. { - int r = fseek(toku_bl_fidx2file(bl, pivots_fidx), 0, SEEK_SET); - if (r!=0) { return get_error_errno(); } + int r = + fseek(toku_bl_fidx2file(bl, pivots_fidx)->file, 0, SEEK_SET); + if (r != 0) { + return get_error_errno(); + } } FIDX next_pivots_file; @@ -3296,7 +3337,7 @@ static int write_nonleaves (FTLOADER bl, FIDX pivots_fidx, struct dbout *out, st while (sts->n_subtrees - n_subtrees_used >= n_per_block*2) { // grab the first N_PER_BLOCK and build a node. DBT *pivots; - int64_t blocknum_of_new_node; + int64_t blocknum_of_new_node = 0; struct subtree_info *subtree_info; int r = setup_nonleaf_block (n_per_block, sts, pivots_fidx, n_subtrees_used, diff --git a/storage/tokudb/PerconaFT/ft/loader/loader.h b/storage/tokudb/PerconaFT/ft/loader/loader.h index 9c1bdab1ee2..cea2e8dfda2 100644 --- a/storage/tokudb/PerconaFT/ft/loader/loader.h +++ b/storage/tokudb/PerconaFT/ft/loader/loader.h @@ -38,6 +38,7 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #pragma once +#include "toku_portability.h" #include "ft/txn/txn.h" #include "ft/cachetable/cachetable.h" #include "ft/comparator.h" @@ -77,8 +78,6 @@ int toku_ft_loader_abort(FTLOADER bl, bool is_error); // For test purposes only -void toku_ft_loader_set_size_factor (uint32_t factor); - -void ft_loader_set_os_fwrite (size_t (*fwrite_fun)(const void*,size_t,size_t,FILE*)); +void toku_ft_loader_set_size_factor(uint32_t factor); size_t ft_loader_leafentry_size(size_t key_size, size_t val_size, TXNID xid); diff --git a/storage/tokudb/PerconaFT/ft/logger/log-internal.h b/storage/tokudb/PerconaFT/ft/logger/log-internal.h index bee74fac346..be19e1342cd 100644 --- a/storage/tokudb/PerconaFT/ft/logger/log-internal.h +++ b/storage/tokudb/PerconaFT/ft/logger/log-internal.h @@ -70,11 +70,11 @@ struct mylock { }; static inline void ml_init(struct mylock *l) { - toku_mutex_init(&l->lock, 0); -} -static inline void ml_lock(struct mylock *l) { - toku_mutex_lock(&l->lock); + toku_mutex_init(*log_internal_lock_mutex_key, &l->lock, nullptr); } +// TODO: source location info might have be to be pulled up one caller +// to be useful +static inline void ml_lock(struct mylock *l) { toku_mutex_lock(&l->lock); } static inline void ml_unlock(struct mylock *l) { toku_mutex_unlock(&l->lock); } diff --git a/storage/tokudb/PerconaFT/ft/logger/logcursor.cc b/storage/tokudb/PerconaFT/ft/logger/logcursor.cc index 910a608cef9..07f57220bf0 100644 --- a/storage/tokudb/PerconaFT/ft/logger/logcursor.cc +++ b/storage/tokudb/PerconaFT/ft/logger/logcursor.cc @@ -86,10 +86,10 @@ static int lc_close_cur_logfile(TOKULOGCURSOR lc) { } static toku_off_t lc_file_len(const char *name) { - toku_struct_stat buf; - int r = toku_stat(name, &buf); - assert(r == 0); - return buf.st_size; + toku_struct_stat buf; + int r = toku_stat(name, &buf, *tokudb_file_data_key); + assert(r == 0); + return buf.st_size; } // Cat the file and throw away the contents. This brings the file into the file system cache diff --git a/storage/tokudb/PerconaFT/ft/logger/logger.cc b/storage/tokudb/PerconaFT/ft/logger/logger.cc index d6d1673b5e3..0e1e5a276b7 100644 --- a/storage/tokudb/PerconaFT/ft/logger/logger.cc +++ b/storage/tokudb/PerconaFT/ft/logger/logger.cc @@ -50,11 +50,17 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "util/status.h" -static const int log_format_version=TOKU_LOG_VERSION; +static const int log_format_version = TOKU_LOG_VERSION; -static int open_logfile (TOKULOGGER logger); -static void logger_write_buffer (TOKULOGGER logger, LSN *fsynced_lsn); -static void delete_logfile(TOKULOGGER logger, long long index, uint32_t version); +toku_instr_key *result_output_condition_lock_mutex_key; +toku_instr_key *result_output_condition_key; +toku_instr_key *tokudb_file_log_key; + +static int open_logfile(TOKULOGGER logger); +static void logger_write_buffer(TOKULOGGER logger, LSN *fsynced_lsn); +static void delete_logfile(TOKULOGGER logger, + long long index, + uint32_t version); static void grab_output(TOKULOGGER logger, LSN *fsynced_lsn); static void release_output(TOKULOGGER logger, LSN fsynced_lsn); @@ -132,10 +138,13 @@ int toku_logger_create (TOKULOGGER *resultp) { // n_in_file is uninitialized result->write_block_size = FT_DEFAULT_NODE_SIZE; // default logging size is the same as the default ft block size toku_logfilemgr_create(&result->logfilemgr); - *resultp=result; + *resultp = result; ml_init(&result->input_lock); - toku_mutex_init(&result->output_condition_lock, NULL); - toku_cond_init(&result->output_condition, NULL); + toku_mutex_init(*result_output_condition_lock_mutex_key, + &result->output_condition_lock, + nullptr); + toku_cond_init( + *result_output_condition_key, &result->output_condition, nullptr); result->rollback_cachefile = NULL; result->output_is_available = true; toku_txn_manager_init(&result->txn_manager); @@ -301,10 +310,10 @@ int toku_logger_close(TOKULOGGER *loggerp) { grab_output(logger, &fsynced_lsn); logger_write_buffer(logger, &fsynced_lsn); if (logger->fd!=-1) { - if ( logger->write_log_files ) { + if (logger->write_log_files) { toku_file_fsync_without_accounting(logger->fd); } - r = close(logger->fd); + r = toku_os_close(logger->fd); assert(r == 0); } r = close_logdir(logger); @@ -346,9 +355,13 @@ static int close_and_open_logfile (TOKULOGGER logger, LSN *fsynced_lsn) if (logger->write_log_files) { toku_file_fsync_without_accounting(logger->fd); *fsynced_lsn = logger->written_lsn; - toku_logfilemgr_update_last_lsn(logger->logfilemgr, logger->written_lsn); // fixes t:2294 + toku_logfilemgr_update_last_lsn(logger->logfilemgr, + logger->written_lsn); // fixes t:2294 } - r = close(logger->fd); if (r!=0) return get_error_errno(); + r = toku_os_close(logger->fd); + + if (r != 0) + return get_error_errno(); return open_logfile(logger); } @@ -678,18 +691,28 @@ static int open_logfile (TOKULOGGER logger) { int fnamelen = strlen(logger->directory)+50; char fname[fnamelen]; - snprintf(fname, fnamelen, "%s/log%012lld.tokulog%d", logger->directory, logger->next_log_file_number, TOKU_LOG_VERSION); + snprintf(fname, + fnamelen, + "%s/log%012lld.tokulog%d", + logger->directory, + logger->next_log_file_number, + TOKU_LOG_VERSION); long long index = logger->next_log_file_number; if (logger->write_log_files) { - logger->fd = open(fname, O_CREAT+O_WRONLY+O_TRUNC+O_EXCL+O_BINARY, S_IRUSR+S_IWUSR); - if (logger->fd==-1) { + logger->fd = + toku_os_open(fname, + O_CREAT + O_WRONLY + O_TRUNC + O_EXCL + O_BINARY, + S_IRUSR + S_IWUSR, + *tokudb_file_log_key); + if (logger->fd == -1) { return get_error_errno(); } fsync_logdir(logger); logger->next_log_file_number++; } else { - logger->fd = open(DEV_NULL_FILE, O_WRONLY+O_BINARY); - if (logger->fd==-1) { + logger->fd = toku_os_open( + DEV_NULL_FILE, O_WRONLY + O_BINARY, S_IWUSR, *tokudb_file_log_key); + if (logger->fd == -1) { return get_error_errno(); } } @@ -835,10 +858,11 @@ int toku_logger_restart(TOKULOGGER logger, LSN lastlsn) logger_write_buffer(logger, &fsynced_lsn); // close the log file - if ( logger->write_log_files) { // fsyncs don't work to /dev/null + if (logger->write_log_files) { // fsyncs don't work to /dev/null toku_file_fsync_without_accounting(logger->fd); } - r = close(logger->fd); assert(r == 0); + r = toku_os_close(logger->fd); + assert(r == 0); logger->fd = -1; // reset the LSN's to the lastlsn when the logger was opened @@ -1238,11 +1262,13 @@ void toku_txnid2txn(TOKULOGGER logger, TXNID_PAIR txnid, TOKUTXN *result) { } // Find the earliest LSN in a log. No locks are needed. -static int peek_at_log (TOKULOGGER logger, char* filename, LSN *first_lsn) { - int fd = open(filename, O_RDONLY+O_BINARY); - if (fd<0) { +static int peek_at_log(TOKULOGGER logger, char *filename, LSN *first_lsn) { + int fd = toku_os_open( + filename, O_RDONLY + O_BINARY, S_IRUSR, *tokudb_file_log_key); + if (fd < 0) { int er = get_error_errno(); - if (logger->write_log_files) printf("couldn't open: %s\n", strerror(er)); + if (logger->write_log_files) + printf("couldn't open: %s\n", strerror(er)); return er; } enum { SKIP = 12+1+4 }; // read the 12 byte header, the first message, and the first len @@ -1259,10 +1285,13 @@ static int peek_at_log (TOKULOGGER logger, char* filename, LSN *first_lsn) { lsn = rbuf_ulonglong(&rb); } - r=close(fd); - if (r!=0) { return 0; } + r = toku_os_close(fd); + + if (r != 0) { + return 0; + } - first_lsn->lsn=lsn; + first_lsn->lsn = lsn; return 0; } diff --git a/storage/tokudb/PerconaFT/ft/logger/recover.cc b/storage/tokudb/PerconaFT/ft/logger/recover.cc index 9eaa56bdc53..9a9a1214ecb 100644 --- a/storage/tokudb/PerconaFT/ft/logger/recover.cc +++ b/storage/tokudb/PerconaFT/ft/logger/recover.cc @@ -954,14 +954,14 @@ static int toku_recover_frename(struct logtype_frename *l, RECOVER_ENV renv) { std::unique_ptr<char[], decltype(&toku_free)> new_iname_full( toku_construct_full_name(2, data_dir, l->new_iname.data), &toku_free); - if (toku_stat(old_iname_full.get(), &stat) == -1) { + if (toku_stat(old_iname_full.get(), &stat, toku_uninstrumented) == -1) { if (ENOENT == errno) old_exist = false; else return 1; } - if (toku_stat(new_iname_full.get(), &stat) == -1) { + if (toku_stat(new_iname_full.get(), &stat, toku_uninstrumented) == -1) { if (ENOENT == errno) new_exist = false; else @@ -980,7 +980,7 @@ static int toku_recover_frename(struct logtype_frename *l, RECOVER_ENV renv) { // 'stalled cachefiles' container the new file is removed // and the old file is renamed. if (old_exist && new_exist && - (toku_os_unlink(new_iname_full.get()) == -1 || + (toku_os_delete(new_iname_full.get()) == -1 || toku_os_rename(old_iname_full.get(), new_iname_full.get()) == -1 || toku_fsync_directory(old_iname_full.get()) == -1 || toku_fsync_directory(new_iname_full.get()) == -1)) @@ -1473,9 +1473,13 @@ static int do_recovery(RECOVER_ENV renv, const char *env_dir, const char *log_di { toku_struct_stat buf; - if (toku_stat(env_dir, &buf)!=0) { + if (toku_stat(env_dir, &buf, toku_uninstrumented)) { rr = get_error_errno(); - fprintf(stderr, "%.24s PerconaFT recovery error: directory does not exist: %s\n", ctime(&tnow), env_dir); + fprintf(stderr, + "%.24s PerconaFT recovery error: directory does not exist: " + "%s\n", + ctime(&tnow), + env_dir); goto errorexit; } else if (!S_ISDIR(buf.st_mode)) { fprintf(stderr, "%.24s PerconaFT recovery error: this file is supposed to be a directory, but is not: %s\n", ctime(&tnow), env_dir); diff --git a/storage/tokudb/PerconaFT/ft/serialize/block_allocator.cc b/storage/tokudb/PerconaFT/ft/serialize/block_allocator.cc index 19811373d16..29f6daa293a 100644 --- a/storage/tokudb/PerconaFT/ft/serialize/block_allocator.cc +++ b/storage/tokudb/PerconaFT/ft/serialize/block_allocator.cc @@ -40,6 +40,7 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include <string.h> +#include "toku_portability.h" #include "portability/memory.h" #include "portability/toku_assert.h" #include "portability/toku_stdint.h" diff --git a/storage/tokudb/PerconaFT/ft/serialize/block_table.cc b/storage/tokudb/PerconaFT/ft/serialize/block_table.cc index 12700d9d83e..811f86c30a7 100644 --- a/storage/tokudb/PerconaFT/ft/serialize/block_table.cc +++ b/storage/tokudb/PerconaFT/ft/serialize/block_table.cc @@ -55,6 +55,11 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "util/nb_mutex.h" #include "util/scoped_malloc.h" + +toku_instr_key *block_table_mutex_key; +toku_instr_key *safe_file_size_lock_mutex_key; +toku_instr_key *safe_file_size_lock_rwlock_key; + // indicates the end of a freelist static const BLOCKNUM freelist_null = {-1}; @@ -100,8 +105,10 @@ void block_table::_create_internal() { memset(&_checkpointed, 0, sizeof(struct translation)); memset(&_mutex, 0, sizeof(_mutex)); _bt_block_allocator = new BlockAllocator(); - toku_mutex_init(&_mutex, nullptr); - nb_mutex_init(&_safe_file_size_lock); + toku_mutex_init(*block_table_mutex_key, &_mutex, nullptr); + nb_mutex_init(*safe_file_size_lock_mutex_key, + *safe_file_size_lock_rwlock_key, + &_safe_file_size_lock); } // Fill in the checkpointed translation from buffer, and copy checkpointed to @@ -129,7 +136,7 @@ int block_table::create_from_buffer( _copy_translation(&_current, &_checkpointed, TRANSLATION_CURRENT); // Determine the file size - int64_t file_size; + int64_t file_size = 0; r = toku_os_get_file_size(fd, &file_size); lazy_assert_zero(r); invariant(file_size >= 0); diff --git a/storage/tokudb/PerconaFT/ft/serialize/ft-serialize.cc b/storage/tokudb/PerconaFT/ft/serialize/ft-serialize.cc index fcab9fc675e..b24d72a5dff 100644 --- a/storage/tokudb/PerconaFT/ft/serialize/ft-serialize.cc +++ b/storage/tokudb/PerconaFT/ft/serialize/ft-serialize.cc @@ -417,8 +417,10 @@ static size_t serialize_ft_min_size(uint32_t version) { switch (version) { case FT_LAYOUT_VERSION_29: size += sizeof(uint64_t); // logrows in ft + // fallthrough case FT_LAYOUT_VERSION_28: size += sizeof(uint32_t); // fanout in ft + // fallthrough case FT_LAYOUT_VERSION_27: case FT_LAYOUT_VERSION_26: case FT_LAYOUT_VERSION_25: @@ -427,10 +429,12 @@ static size_t serialize_ft_min_size(uint32_t version) { case FT_LAYOUT_VERSION_22: case FT_LAYOUT_VERSION_21: size += sizeof(MSN); // max_msn_in_ft + // fallthrough case FT_LAYOUT_VERSION_20: case FT_LAYOUT_VERSION_19: size += 1; // compression method size += sizeof(MSN); // highest_unused_msn_for_upgrade + // fallthrough case FT_LAYOUT_VERSION_18: size += sizeof(uint64_t); // time_of_last_optimize_begin size += sizeof(uint64_t); // time_of_last_optimize_end @@ -438,9 +442,11 @@ static size_t serialize_ft_min_size(uint32_t version) { size += sizeof(MSN); // msn_at_start_of_last_completed_optimize size -= 8; // removed num_blocks_to_upgrade_14 size -= 8; // removed num_blocks_to_upgrade_13 + // fallthrough case FT_LAYOUT_VERSION_17: size += 16; invariant(sizeof(STAT64INFO_S) == 16); + // fallthrough case FT_LAYOUT_VERSION_16: case FT_LAYOUT_VERSION_15: size += 4; // basement node size @@ -448,8 +454,10 @@ static size_t serialize_ft_min_size(uint32_t version) { // num_blocks_to_upgrade, now one int each for upgrade // from 13, 14 size += 8; // time of last verification + // fallthrough case FT_LAYOUT_VERSION_14: size += 8; // TXNID that created + // fallthrough case FT_LAYOUT_VERSION_13: size += (4 // build_id + @@ -459,7 +467,7 @@ static size_t serialize_ft_min_size(uint32_t version) { + 8 // time_of_last_modification ); - // fall through + // fallthrough case FT_LAYOUT_VERSION_12: size += (+8 // "tokudata" + diff --git a/storage/tokudb/PerconaFT/ft/serialize/sub_block.cc b/storage/tokudb/PerconaFT/ft/serialize/sub_block.cc index c967d4b4c1c..6dc1f82844a 100644 --- a/storage/tokudb/PerconaFT/ft/serialize/sub_block.cc +++ b/storage/tokudb/PerconaFT/ft/serialize/sub_block.cc @@ -51,6 +51,9 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "util/threadpool.h" #include "util/x1764.h" +toku_instr_key *workset_lock_mutex_key; +toku_instr_key *ws_worker_wait_key; + SUB_BLOCK sub_block_creat(void) { SUB_BLOCK XMALLOC(sb); sub_block_init(sb); diff --git a/storage/tokudb/PerconaFT/ft/serialize/workset.h b/storage/tokudb/PerconaFT/ft/serialize/workset.h index 073741fccb1..295eb73cec9 100644 --- a/storage/tokudb/PerconaFT/ft/serialize/workset.h +++ b/storage/tokudb/PerconaFT/ft/serialize/workset.h @@ -41,6 +41,8 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include <toku_list.h> #include <toku_pthread.h> +extern toku_instr_key *ws_worker_wait_key; + // The work struct is the base class for work to be done by some threads struct work { struct toku_list next; @@ -54,16 +56,14 @@ struct workset { toku_cond_t worker_wait; // a condition variable used to wait for all of the worker to release their reference on the workset }; -static inline void -workset_init(struct workset *ws) { - toku_mutex_init(&ws->lock, NULL); +static inline void workset_init(struct workset *ws) { + toku_mutex_init(*workset_lock_mutex_key, &ws->lock, nullptr); toku_list_init(&ws->worklist); - ws->refs = 1; // the calling thread gets a reference - toku_cond_init(&ws->worker_wait, NULL); + ws->refs = 1; // the calling thread gets a reference + toku_cond_init(*ws_worker_wait_key, &ws->worker_wait, nullptr); } -static inline void -workset_destroy(struct workset *ws) { +static inline void workset_destroy(struct workset *ws) { invariant(toku_list_empty(&ws->worklist)); toku_cond_destroy(&ws->worker_wait); toku_mutex_destroy(&ws->lock); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-4357.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-4357.cc index 8bbda295462..0af5c8185a9 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-4357.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-4357.cc @@ -71,21 +71,26 @@ cachetable_test (void) { void* v1; long s1; - r = toku_cachetable_get_and_pin( - f1, - make_blocknum(1), - toku_cachetable_hash(f1, make_blocknum(1)), - &v1, - &s1, - def_write_callback(NULL), def_fetch, def_pf_req_callback, def_pf_callback, - true, - NULL - ); + r = toku_cachetable_get_and_pin(f1, + make_blocknum(1), + toku_cachetable_hash(f1, make_blocknum(1)), + &v1, + &s1, + def_write_callback(NULL), + def_fetch, + def_pf_req_callback, + def_pf_callback, + true, + NULL); toku_pthread_t pin_nonblocking_tid; - r = toku_pthread_create(&pin_nonblocking_tid, NULL, pin_nonblocking, NULL); - assert_zero(r); + r = toku_pthread_create(toku_uninstrumented, + &pin_nonblocking_tid, + nullptr, + pin_nonblocking, + nullptr); + assert_zero(r); // sleep 3 seconds - usleep(3*1024*1024); + usleep(3 * 1024 * 1024); r = toku_test_cachetable_unpin_and_remove(f1, make_blocknum(1), NULL, NULL); assert_zero(r); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-4365.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-4365.cc index 9c54c086f5b..7bee0b80770 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-4365.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-4365.cc @@ -71,15 +71,16 @@ static void *put_same_key(void *arg) { return arg; } - toku_pthread_t put_tid; -static void test_remove_key(CACHEKEY* UU(cachekey), bool UU(for_checkpoint), void* UU(extra)) { - int r = toku_pthread_create(&put_tid, NULL, put_same_key, NULL); - assert_zero(r); +static void test_remove_key(CACHEKEY *UU(cachekey), + bool UU(for_checkpoint), + void *UU(extra)) { + int r = toku_pthread_create( + toku_uninstrumented, &put_tid, nullptr, put_same_key, nullptr); + assert_zero(r); } - static void cachetable_test (void) { const int test_limit = 12; @@ -92,21 +93,26 @@ cachetable_test (void) { void* v1; long s1; - r = toku_cachetable_get_and_pin( - f1, - make_blocknum(1), - toku_cachetable_hash(f1, make_blocknum(1)), - &v1, - &s1, - def_write_callback(NULL), def_fetch, def_pf_req_callback, def_pf_callback, - true, - NULL - ); + r = toku_cachetable_get_and_pin(f1, + make_blocknum(1), + toku_cachetable_hash(f1, make_blocknum(1)), + &v1, + &s1, + def_write_callback(nullptr), + def_fetch, + def_pf_req_callback, + def_pf_callback, + true, + nullptr); toku_pthread_t pin_nonblocking_tid; - r = toku_pthread_create(&pin_nonblocking_tid, NULL, pin_nonblocking, NULL); - assert_zero(r); + r = toku_pthread_create(toku_uninstrumented, + &pin_nonblocking_tid, + nullptr, + pin_nonblocking, + nullptr); + assert_zero(r); // sleep 3 seconds - usleep(3*1024*1024); + usleep(3 * 1024 * 1024); r = toku_test_cachetable_unpin_and_remove(f1, make_blocknum(1), test_remove_key, NULL); assert_zero(r); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-5097.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-5097.cc index c1b6e0a94f2..5ab0df88e08 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-5097.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-5097.cc @@ -153,13 +153,16 @@ cachetable_test (void) { assert(r == 0); } - // at this point, we have a dirty PAIR in the cachetable associated with cachefile f1 - // launch a thread that will put another PAIR in the cachetable, and get partial eviction started + // at this point, we have a dirty PAIR in the cachetable associated with + // cachefile f1 + // launch a thread that will put another PAIR in the cachetable, and get + // partial eviction started toku_pthread_t tid; - r = toku_pthread_create(&tid, NULL, f2_pin, NULL); + r = toku_pthread_create( + toku_uninstrumented, &tid, nullptr, f2_pin, nullptr); assert_zero(r); - usleep(2*1024*1024); + usleep(2 * 1024 * 1024); check_flush = true; toku_cachefile_close(&f1, false, ZERO_LSN); if (enable_partial_eviction) diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-5978-2.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-5978-2.cc index b462d76eeee..0b5110ddd99 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-5978-2.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-5978-2.cc @@ -114,14 +114,14 @@ unpin_two (void* UU(v)) { ); assert_zero(r); - // at this point, we have p1 pinned, want to start a thread to do an unpin_and_remove - // on p1 - r = toku_pthread_create( - &unpin_and_remove_tid, - NULL, - unpin_and_remove_one, - NULL - ); + // at this point, we have p1 pinned, want to start a thread to do an + // unpin_and_remove + // on p1 + r = toku_pthread_create(toku_uninstrumented, + &unpin_and_remove_tid, + nullptr, + unpin_and_remove_one, + nullptr); assert_zero(r); // sleep to give a chance for the unpin_and_remove to get going usleep(512*1024); @@ -173,9 +173,9 @@ cachetable_test (void) { r = toku_cachetable_get_and_pin(f1, make_blocknum(2), 2, &v1, &s1, wc, fetch_two, def_pf_req_callback, def_pf_callback, true, NULL); assert_zero(r); - toku_pthread_t tid1; - r = toku_pthread_create(&tid1, NULL, repin_one, NULL); + r = toku_pthread_create( + toku_uninstrumented, &tid1, nullptr, repin_one, nullptr); assert_zero(r); void *ret; diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-5978.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-5978.cc index ee68ab3ef0b..a4ff6c33e6a 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-5978.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-5978.cc @@ -199,9 +199,11 @@ cachetable_test (void) { toku_pthread_t tid1; toku_pthread_t tid2; - r = toku_pthread_create(&tid1, NULL, repin_one, NULL); + r = toku_pthread_create( + toku_uninstrumented, &tid1, nullptr, repin_one, nullptr); assert_zero(r); - r = toku_pthread_create(&tid2, NULL, repin_two, NULL); + r = toku_pthread_create( + toku_uninstrumented, &tid2, nullptr, repin_two, nullptr); assert_zero(r); // unpin 1 and 2 so tid1 and tid2 can make progress diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-checkpoint-pending.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-checkpoint-pending.cc index 3dd3a15e2de..5e87fed740d 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-checkpoint-pending.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-checkpoint-pending.cc @@ -158,14 +158,24 @@ static void checkpoint_pending(void) { // the checkpoint should cause n writes, but since n <= the cachetable size, // all items should be kept in the cachetable - n_flush = n_write_me = n_keep_me = n_fetch = 0; expect_value = 42; - //printf("E42\n"); + n_flush = n_write_me = n_keep_me = n_fetch = 0; + expect_value = 42; + // printf("E42\n"); toku_pthread_t checkpoint_thread, update_thread; - r = toku_pthread_create(&checkpoint_thread, NULL, do_checkpoint, NULL); assert(r==0); - r = toku_pthread_create(&update_thread, NULL, do_update, NULL); assert(r==0); - r = toku_pthread_join(checkpoint_thread, 0); assert(r==0); - r = toku_pthread_join(update_thread, 0); assert(r==0); - + r = toku_pthread_create(toku_uninstrumented, + &checkpoint_thread, + nullptr, + do_checkpoint, + nullptr); + assert(r == 0); + r = toku_pthread_create( + toku_uninstrumented, &update_thread, nullptr, do_update, nullptr); + assert(r == 0); + r = toku_pthread_join(checkpoint_thread, 0); + assert(r == 0); + r = toku_pthread_join(update_thread, 0); + assert(r == 0); + assert(n_flush == N && n_write_me == N && n_keep_me == N); // after the checkpoint, all of the items should be 43 diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-cleaner-thread-attrs-accumulate.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-cleaner-thread-attrs-accumulate.cc index c1e7b373e83..dd6c674af24 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-cleaner-thread-attrs-accumulate.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-cleaner-thread-attrs-accumulate.cc @@ -91,7 +91,7 @@ run_test (void) { const int test_limit = 1000; int r; CACHETABLE ct; - toku_mutex_init(&attr_mutex, NULL); + toku_mutex_init(toku_uninstrumented, &attr_mutex, nullptr); toku_cachetable_create(&ct, test_limit, ZERO_LSN, nullptr); const char *fname1 = TOKU_TEST_FILENAME; diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-clone-checkpoint.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-clone-checkpoint.cc index 50bd20f492e..99d595b1ff1 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-clone-checkpoint.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-clone-checkpoint.cc @@ -112,14 +112,17 @@ cachetable_test (void) { CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct); toku_cachetable_begin_checkpoint(cp, NULL); - clone_flush_started = false; clone_flush_completed = false; toku_pthread_t checkpoint_tid; - r = toku_pthread_create(&checkpoint_tid, NULL, run_end_checkpoint, NULL); - assert_zero(r); + r = toku_pthread_create(toku_uninstrumented, + &checkpoint_tid, + nullptr, + run_end_checkpoint, + nullptr); + assert_zero(r); - usleep(1*1024*1024); + usleep(1 * 1024 * 1024); r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, &s1, wc, def_fetch, def_pf_req_callback, def_pf_callback, true, NULL); assert_zero(r); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-pin-checkpoint.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-pin-checkpoint.cc index 8a270af0566..65b02aebaec 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-pin-checkpoint.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-pin-checkpoint.cc @@ -386,19 +386,28 @@ cachetable_test (void) { run_test = true; for (int i = 0; i < NUM_MOVER_THREADS; i++) { - r = toku_pthread_create(&read_random_tid[i], NULL, read_random_numbers, NULL); + r = toku_pthread_create(toku_uninstrumented, + &read_random_tid[i], + nullptr, + read_random_numbers, + nullptr); assert_zero(r); } for (int i = 0; i < NUM_MOVER_THREADS; i++) { - r = toku_pthread_create(&move_tid[i], NULL, move_numbers, NULL); + r = toku_pthread_create(toku_uninstrumented, + &move_tid[i], + nullptr, + move_numbers, + nullptr); assert_zero(r); } - r = toku_pthread_create(&checkpoint_tid, NULL, checkpoints, NULL); - assert_zero(r); - r = toku_pthread_create(&time_tid, NULL, test_time, NULL); + r = toku_pthread_create( + toku_uninstrumented, &checkpoint_tid, nullptr, checkpoints, nullptr); + assert_zero(r); + r = toku_pthread_create( + toku_uninstrumented, &time_tid, nullptr, test_time, nullptr); assert_zero(r); - void *ret; r = toku_pthread_join(time_tid, &ret); assert_zero(r); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-put-checkpoint.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-put-checkpoint.cc index afc95471116..4cf1678449b 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-put-checkpoint.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-put-checkpoint.cc @@ -518,19 +518,28 @@ cachetable_test (void) { run_test = true; for (int i = 0; i < NUM_MOVER_THREADS; i++) { - r = toku_pthread_create(&move_tid[i], NULL, move_numbers, NULL); + r = toku_pthread_create(toku_uninstrumented, + &move_tid[i], + nullptr, + move_numbers, + nullptr); assert_zero(r); } for (int i = 0; i < NUM_MOVER_THREADS; i++) { - r = toku_pthread_create(&merge_and_split_tid[i], NULL, merge_and_split, NULL); + r = toku_pthread_create(toku_uninstrumented, + &merge_and_split_tid[i], + nullptr, + merge_and_split, + nullptr); assert_zero(r); } - r = toku_pthread_create(&checkpoint_tid, NULL, checkpoints, NULL); - assert_zero(r); - r = toku_pthread_create(&time_tid, NULL, test_time, NULL); + r = toku_pthread_create( + toku_uninstrumented, &checkpoint_tid, nullptr, checkpoints, nullptr); + assert_zero(r); + r = toku_pthread_create( + toku_uninstrumented, &time_tid, nullptr, test_time, nullptr); assert_zero(r); - void *ret; r = toku_pthread_join(time_tid, &ret); assert_zero(r); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-rwlock-test.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-rwlock-test.cc index 9a62f99e1fa..6d8bc28026c 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-rwlock-test.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-rwlock-test.cc @@ -40,24 +40,22 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. // test create and destroy -static void -test_create_destroy (void) { - struct rwlock the_rwlock, *rwlock = &the_rwlock; +static void test_create_destroy(void) { + struct st_rwlock the_rwlock, *rwlock = &the_rwlock; - rwlock_init(rwlock); + rwlock_init(toku_uninstrumented, rwlock); rwlock_destroy(rwlock); } // test read lock and unlock with no writers -static void -test_simple_read_lock (int n) { - struct rwlock the_rwlock, *rwlock = &the_rwlock; +static void test_simple_read_lock(int n) { + struct st_rwlock the_rwlock, *rwlock = &the_rwlock; - rwlock_init(rwlock); + rwlock_init(toku_uninstrumented, rwlock); assert(rwlock_readers(rwlock) == 0); int i; - for (i=1; i<=n; i++) { + for (i = 1; i <= n; i++) { rwlock_read_lock(rwlock, 0); assert(rwlock_readers(rwlock) == i); assert(rwlock_users(rwlock) == i); @@ -72,11 +70,10 @@ test_simple_read_lock (int n) { // test write lock and unlock with no readers -static void -test_simple_write_lock (void) { - struct rwlock the_rwlock, *rwlock = &the_rwlock; +static void test_simple_write_lock(void) { + struct st_rwlock the_rwlock, *rwlock = &the_rwlock; - rwlock_init(rwlock); + rwlock_init(toku_uninstrumented, rwlock); assert(rwlock_users(rwlock) == 0); rwlock_write_lock(rwlock, 0); assert(rwlock_writers(rwlock) == 1); @@ -88,19 +85,17 @@ test_simple_write_lock (void) { struct rw_event { int e; - struct rwlock the_rwlock; + struct st_rwlock the_rwlock; toku_mutex_t mutex; }; -static void -rw_event_init (struct rw_event *rwe) { +static void rw_event_init(struct rw_event *rwe) { rwe->e = 0; - rwlock_init(&rwe->the_rwlock); - toku_mutex_init(&rwe->mutex, 0); + rwlock_init(toku_uninstrumented, &rwe->the_rwlock); + toku_mutex_init(toku_uninstrumented, &rwe->mutex, nullptr); } -static void -rw_event_destroy (struct rw_event *rwe) { +static void rw_event_destroy(struct rw_event *rwe) { rwlock_destroy(&rwe->the_rwlock); toku_mutex_destroy(&rwe->mutex); } @@ -138,10 +133,12 @@ test_writer_priority (void) { toku_mutex_unlock(&rwe->mutex); toku_pthread_t tid; - r = toku_pthread_create(&tid, 0, test_writer_priority_thread, rwe); + r = toku_pthread_create( + toku_uninstrumented, &tid, 0, test_writer_priority_thread, rwe); sleep(1); toku_mutex_lock(&rwe->mutex); - rwe->e++; assert(rwe->e == 2); + rwe->e++; + assert(rwe->e == 2); toku_mutex_unlock(&rwe->mutex); sleep(1); @@ -196,10 +193,12 @@ test_single_writer (void) { toku_mutex_unlock(&rwe->mutex); toku_pthread_t tid; - r = toku_pthread_create(&tid, 0, test_single_writer_thread, rwe); + r = toku_pthread_create( + toku_uninstrumented, &tid, 0, test_single_writer_thread, rwe); sleep(1); toku_mutex_lock(&rwe->mutex); - rwe->e++; assert(rwe->e == 2); + rwe->e++; + assert(rwe->e == 2); assert(rwlock_writers(&rwe->the_rwlock) == 1); assert(rwlock_users(&rwe->the_rwlock) == 2); rwlock_write_unlock(&rwe->the_rwlock); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-simple-read-pin-nonblocking.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-simple-read-pin-nonblocking.cc index 8fd8828737a..ebe05e50883 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-simple-read-pin-nonblocking.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-simple-read-pin-nonblocking.cc @@ -111,9 +111,20 @@ run_test (void) { toku_pthread_t fetch_tid; fetch_called = false; - r = toku_pthread_create(&fetch_tid, NULL, run_expensive_fetch, NULL); + r = toku_pthread_create( + toku_uninstrumented, &fetch_tid, nullptr, run_expensive_fetch, nullptr); sleep(1); - r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, &s1, wc, sleep_fetch, def_pf_req_callback, def_pf_callback, false, NULL); + r = toku_cachetable_get_and_pin(f1, + make_blocknum(1), + 1, + &v1, + &s1, + wc, + sleep_fetch, + def_pf_req_callback, + def_pf_callback, + false, + NULL); assert_zero(r); assert(fetch_called); r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8)); @@ -133,9 +144,20 @@ run_test (void) { toku_pthread_t pf_tid; pf_called = false; - r = toku_pthread_create(&pf_tid, NULL, run_expensive_pf, NULL); + r = toku_pthread_create( + toku_uninstrumented, &pf_tid, nullptr, run_expensive_pf, nullptr); sleep(1); - r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, &s1, wc, sleep_fetch, def_pf_req_callback, def_pf_callback, false, NULL); + r = toku_cachetable_get_and_pin(f1, + make_blocknum(1), + 1, + &v1, + &s1, + wc, + sleep_fetch, + def_pf_req_callback, + def_pf_callback, + false, + NULL); assert_zero(r); assert(pf_called); r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8)); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-simple-read-pin.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-simple-read-pin.cc index 63ca871a459..dd5d59df002 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-simple-read-pin.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-simple-read-pin.cc @@ -117,9 +117,20 @@ run_test (void) { toku_pthread_t fetch_tid; fetch_called = false; - r = toku_pthread_create(&fetch_tid, NULL, run_expensive_fetch, NULL); + r = toku_pthread_create( + toku_uninstrumented, &fetch_tid, nullptr, run_expensive_fetch, nullptr); sleep(1); - r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, &s1, wc, sleep_fetch, def_pf_req_callback, def_pf_callback, false, NULL); + r = toku_cachetable_get_and_pin(f1, + make_blocknum(1), + 1, + &v1, + &s1, + wc, + sleep_fetch, + def_pf_req_callback, + def_pf_callback, + false, + NULL); assert_zero(r); assert(fetch_called); r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8)); @@ -141,9 +152,20 @@ run_test (void) { toku_pthread_t pf_tid; pf_called = false; - r = toku_pthread_create(&pf_tid, NULL, run_expensive_pf, NULL); + r = toku_pthread_create( + toku_uninstrumented, &pf_tid, nullptr, run_expensive_pf, nullptr); sleep(1); - r = toku_cachetable_get_and_pin(f1, make_blocknum(1), 1, &v1, &s1, wc, sleep_fetch, def_pf_req_callback, def_pf_callback, false, NULL); + r = toku_cachetable_get_and_pin(f1, + make_blocknum(1), + 1, + &v1, + &s1, + wc, + sleep_fetch, + def_pf_req_callback, + def_pf_callback, + false, + NULL); assert_zero(r); assert(pf_called); r = toku_test_cachetable_unpin(f1, make_blocknum(1), 1, CACHETABLE_CLEAN, make_pair_attr(8)); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-test.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-test.cc index e4bb5fb0aea..64f688c470d 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-test.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-test.cc @@ -42,15 +42,13 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. // global data, especially between the test thread and the cachetable // writeback threads -toku_mutex_t test_mutex; +toku_mutex_t test_mutex; static inline void test_mutex_init(void) { - toku_mutex_init(&test_mutex, 0); + toku_mutex_init(toku_uninstrumented, &test_mutex, nullptr); } -static inline void test_mutex_destroy(void) { - toku_mutex_destroy(&test_mutex); -} +static inline void test_mutex_destroy(void) { toku_mutex_destroy(&test_mutex); } static inline void test_mutex_lock(void) { toku_mutex_lock(&test_mutex); diff --git a/storage/tokudb/PerconaFT/ft/tests/cachetable-unpin-remove-and-checkpoint.cc b/storage/tokudb/PerconaFT/ft/tests/cachetable-unpin-remove-and-checkpoint.cc index 11baa36e51b..0e44bf10349 100644 --- a/storage/tokudb/PerconaFT/ft/tests/cachetable-unpin-remove-and-checkpoint.cc +++ b/storage/tokudb/PerconaFT/ft/tests/cachetable-unpin-remove-and-checkpoint.cc @@ -86,11 +86,22 @@ run_test (void) { // now this should mark the pair for checkpoint CHECKPOINTER cp = toku_cachetable_get_checkpointer(ct); toku_cachetable_begin_checkpoint(cp, NULL); - r = toku_cachetable_get_and_pin(f1, make_blocknum(1), toku_cachetable_hash(f1, make_blocknum(1)), &v1, &s1, wc, def_fetch, def_pf_req_callback, def_pf_callback, true, NULL); + r = toku_cachetable_get_and_pin(f1, + make_blocknum(1), + toku_cachetable_hash(f1, make_blocknum(1)), + &v1, + &s1, + wc, + def_fetch, + def_pf_req_callback, + def_pf_callback, + true, + NULL); toku_pthread_t mytid; - r = toku_pthread_create(&mytid, NULL, run_end_chkpt, NULL); - assert(r==0); + r = toku_pthread_create( + toku_uninstrumented, &mytid, nullptr, run_end_chkpt, nullptr); + assert(r == 0); // give checkpoint thread a chance to start waiting on lock sleep(1); diff --git a/storage/tokudb/PerconaFT/ft/tests/ftloader-test-extractor-errors.cc b/storage/tokudb/PerconaFT/ft/tests/ftloader-test-extractor-errors.cc index 872b674c784..4bff52ceb1b 100644 --- a/storage/tokudb/PerconaFT/ft/tests/ftloader-test-extractor-errors.cc +++ b/storage/tokudb/PerconaFT/ft/tests/ftloader-test-extractor-errors.cc @@ -141,7 +141,7 @@ static void test_extractor(int nrows, int nrowsets, bool expect_fail, const char // setup error injection toku_set_func_malloc(my_malloc); toku_set_func_realloc(my_realloc); - ft_loader_set_os_fwrite(bad_fwrite); + toku_set_func_fwrite(bad_fwrite); toku_set_func_write(bad_write); toku_set_func_pwrite(bad_pwrite); ft_loader_set_poll_function(&loader->poll_callback, loader_poll_callback, NULL); @@ -157,7 +157,7 @@ static void test_extractor(int nrows, int nrowsets, bool expect_fail, const char toku_set_func_malloc(NULL); toku_set_func_realloc(NULL); - ft_loader_set_os_fwrite(NULL); + toku_set_func_fwrite(nullptr); toku_set_func_write(NULL); toku_set_func_pwrite(NULL); diff --git a/storage/tokudb/PerconaFT/ft/tests/ftloader-test-merge-files-dbufio.cc b/storage/tokudb/PerconaFT/ft/tests/ftloader-test-merge-files-dbufio.cc index d1aeff198ff..0b121316738 100644 --- a/storage/tokudb/PerconaFT/ft/tests/ftloader-test-merge-files-dbufio.cc +++ b/storage/tokudb/PerconaFT/ft/tests/ftloader-test-merge-files-dbufio.cc @@ -393,13 +393,17 @@ static void test (const char *directory, bool is_error) { toku_pthread_t consumer; struct consumer_thunk cthunk = {q, 0}; { - int r = toku_pthread_create(&consumer, NULL, consumer_thread, (void*)&cthunk); - assert(r==0); + int r = toku_pthread_create(toku_uninstrumented, + &consumer, + nullptr, + consumer_thread, + static_cast<void *>(&cthunk)); + assert(r == 0); } toku_set_func_malloc_only(my_malloc); toku_set_func_realloc_only(my_realloc); - ft_loader_set_os_fwrite(bad_fwrite); + toku_set_func_fwrite(bad_fwrite); toku_set_func_write(bad_write); toku_set_func_pwrite(bad_pwrite); toku_set_func_fdopen(bad_fdopen); @@ -427,7 +431,7 @@ static void test (const char *directory, bool is_error) { toku_set_func_malloc(NULL); toku_set_func_realloc(NULL); - ft_loader_set_os_fwrite(NULL); + toku_set_func_fwrite(nullptr); toku_set_func_write(NULL); toku_set_func_pwrite(NULL); toku_set_func_fdopen(NULL); diff --git a/storage/tokudb/PerconaFT/ft/tests/ftloader-test-writer-errors.cc b/storage/tokudb/PerconaFT/ft/tests/ftloader-test-writer-errors.cc index 0784ca87a26..e4423319518 100644 --- a/storage/tokudb/PerconaFT/ft/tests/ftloader-test-writer-errors.cc +++ b/storage/tokudb/PerconaFT/ft/tests/ftloader-test-writer-errors.cc @@ -154,7 +154,7 @@ static int write_dbfile (char *tf_template, int n, char *output_name, bool expec toku_set_func_malloc_only(my_malloc); toku_set_func_realloc_only(my_realloc); - ft_loader_set_os_fwrite(bad_fwrite); + toku_set_func_fwrite(bad_fwrite); toku_set_func_write(bad_write); toku_set_func_pwrite(bad_pwrite); ft_loader_set_error_function(&bl.error_callback, NULL, NULL); @@ -164,7 +164,7 @@ static int write_dbfile (char *tf_template, int n, char *output_name, bool expec toku_set_func_malloc_only(NULL); toku_set_func_realloc_only(NULL); - ft_loader_set_os_fwrite(NULL); + toku_set_func_fwrite(nullptr); toku_set_func_write(NULL); toku_set_func_pwrite(NULL); diff --git a/storage/tokudb/PerconaFT/ft/tests/log-test4.cc b/storage/tokudb/PerconaFT/ft/tests/log-test4.cc index a31181deb30..e0bbedb95bf 100644 --- a/storage/tokudb/PerconaFT/ft/tests/log-test4.cc +++ b/storage/tokudb/PerconaFT/ft/tests/log-test4.cc @@ -63,11 +63,14 @@ test_main (int argc __attribute__((__unused__)), r = toku_logger_close(&logger); assert(r == 0); { - toku_struct_stat statbuf; - sprintf(logname, "%s/log000000000000.tokulog%d", TOKU_TEST_FILENAME, TOKU_LOG_VERSION); - r = toku_stat(logname, &statbuf); - assert(r==0); - assert(statbuf.st_size==12+5); + toku_struct_stat statbuf; + sprintf(logname, + "%s/log000000000000.tokulog%d", + TOKU_TEST_FILENAME, + TOKU_LOG_VERSION); + r = toku_stat(logname, &statbuf, toku_uninstrumented); + assert(r == 0); + assert(statbuf.st_size == 12 + 5); } toku_os_recursive_delete(TOKU_TEST_FILENAME); return 0; diff --git a/storage/tokudb/PerconaFT/ft/tests/log-test5.cc b/storage/tokudb/PerconaFT/ft/tests/log-test5.cc index d4e31af22dc..fed9467a4ae 100644 --- a/storage/tokudb/PerconaFT/ft/tests/log-test5.cc +++ b/storage/tokudb/PerconaFT/ft/tests/log-test5.cc @@ -81,14 +81,14 @@ test_main (int argc __attribute__((__unused__)), struct dirent *dirent; while ((dirent=readdir(dir))) { if (strncmp(dirent->d_name, "log", 3)!=0) continue; - char fname[TOKU_PATH_MAX+1]; - toku_path_join(fname, 2, TOKU_TEST_FILENAME, dirent->d_name); - toku_struct_stat statbuf; - r = toku_stat(fname, &statbuf); - assert(r==0); - assert(statbuf.st_size<=LSIZE+10); - } - r = closedir(dir); + char fname[TOKU_PATH_MAX + 1]; + toku_path_join(fname, 2, TOKU_TEST_FILENAME, dirent->d_name); + toku_struct_stat statbuf; + r = toku_stat(fname, &statbuf, toku_uninstrumented); + assert(r == 0); + assert(statbuf.st_size <= LSIZE + 10); + } + r = closedir(dir); assert(r==0); } toku_os_recursive_delete(TOKU_TEST_FILENAME); diff --git a/storage/tokudb/PerconaFT/ft/tests/log-test6.cc b/storage/tokudb/PerconaFT/ft/tests/log-test6.cc index 4d17488c57c..0e8b94566df 100644 --- a/storage/tokudb/PerconaFT/ft/tests/log-test6.cc +++ b/storage/tokudb/PerconaFT/ft/tests/log-test6.cc @@ -86,11 +86,14 @@ test_main (int argc __attribute__((__unused__)), { char logname[PATH_MAX]; - toku_struct_stat statbuf; - sprintf(logname, "%s/log000000000000.tokulog%d", TOKU_TEST_FILENAME, TOKU_LOG_VERSION); - r = toku_stat(logname, &statbuf); - assert(r==0); - assert(statbuf.st_size<=LSIZE); + toku_struct_stat statbuf; + sprintf(logname, + "%s/log000000000000.tokulog%d", + TOKU_TEST_FILENAME, + TOKU_LOG_VERSION); + r = toku_stat(logname, &statbuf, toku_uninstrumented); + assert(r == 0); + assert(statbuf.st_size <= LSIZE); } toku_os_recursive_delete(TOKU_TEST_FILENAME); return 0; diff --git a/storage/tokudb/PerconaFT/ft/tests/recovery-bad-last-entry.cc b/storage/tokudb/PerconaFT/ft/tests/recovery-bad-last-entry.cc index 431ee4b5e50..a3c934d1f4b 100644 --- a/storage/tokudb/PerconaFT/ft/tests/recovery-bad-last-entry.cc +++ b/storage/tokudb/PerconaFT/ft/tests/recovery-bad-last-entry.cc @@ -83,11 +83,16 @@ run_test(void) { r = toku_dup2(devnul, fileno(stderr)); assert(r==fileno(stderr)); r = close(devnul); assert(r==0); - char fname[TOKU_PATH_MAX+1]; - sprintf(fname, "%s/%s%d", TOKU_TEST_FILENAME, "log000000000000.tokulog", TOKU_LOG_VERSION); - - r = toku_stat(fname, &st); assert(r==0); - if ( st.st_size - trim > magic_begin_end_checkpoint_sz ) { + char fname[TOKU_PATH_MAX + 1]; + sprintf(fname, + "%s/%s%d", + TOKU_TEST_FILENAME, + "log000000000000.tokulog", + TOKU_LOG_VERSION); + + r = toku_stat(fname, &st, toku_uninstrumented); + assert(r == 0); + if (st.st_size - trim > magic_begin_end_checkpoint_sz) { r = truncate(fname, st.st_size - trim); CKERR(r); } diff --git a/storage/tokudb/PerconaFT/ft/tests/test-bjm.cc b/storage/tokudb/PerconaFT/ft/tests/test-bjm.cc index 97e00c42b95..6afe5b9f7c4 100644 --- a/storage/tokudb/PerconaFT/ft/tests/test-bjm.cc +++ b/storage/tokudb/PerconaFT/ft/tests/test-bjm.cc @@ -71,12 +71,16 @@ static void bjm_test(void) { bjm_reset(bjm); r = bjm_add_background_job(bjm); - assert_zero(r); - toku_pthread_t tid; - r = toku_pthread_create(&tid, NULL, finish_bjm, NULL); assert_zero(r); - usleep(2*1024*1024); - // should return non-zero because tid is waiting + toku_pthread_t tid; + r = toku_pthread_create(toku_uninstrumented, + &tid, + nullptr, + finish_bjm, + nullptr); + assert_zero(r); + usleep(2 * 1024 * 1024); + // should return non-zero because tid is waiting // for background jobs to finish r = bjm_add_background_job(bjm); assert(r != 0); diff --git a/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-flush.cc b/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-flush.cc index 3e5d9bba817..06a26614885 100644 --- a/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-flush.cc +++ b/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-flush.cc @@ -113,10 +113,14 @@ static void flusher_callback(int state, void* extra) { if ((state == flt_flush_before_child_pin && !after_child_pin) || (state == ft_flush_aflter_child_pin && after_child_pin)) { checkpoint_called = true; - int r = toku_pthread_create(&checkpoint_tid, NULL, do_checkpoint, NULL); + int r = toku_pthread_create(toku_uninstrumented, + &checkpoint_tid, + nullptr, + do_checkpoint, + nullptr); assert_zero(r); while (!checkpoint_callback_called) { - usleep(1*1024*1024); + usleep(1 * 1024 * 1024); } } } diff --git a/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-merge.cc b/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-merge.cc index cb316127ef7..1029dfef320 100644 --- a/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-merge.cc +++ b/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-merge.cc @@ -103,10 +103,14 @@ static void flusher_callback(int state, void* extra) { } if (state == desired_state) { checkpoint_called = true; - int r = toku_pthread_create(&checkpoint_tid, NULL, do_checkpoint, NULL); + int r = toku_pthread_create(toku_uninstrumented, + &checkpoint_tid, + nullptr, + do_checkpoint, + nullptr); assert_zero(r); while (!checkpoint_callback_called) { - usleep(1*1024*1024); + usleep(1 * 1024 * 1024); } } } diff --git a/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-rebalance.cc b/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-rebalance.cc index 5f8485ac4ec..208ebe3ca31 100644 --- a/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-rebalance.cc +++ b/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-rebalance.cc @@ -103,10 +103,14 @@ static void flusher_callback(int state, void* extra) { } if (state == desired_state) { checkpoint_called = true; - int r = toku_pthread_create(&checkpoint_tid, NULL, do_checkpoint, NULL); + int r = toku_pthread_create(toku_uninstrumented, + &checkpoint_tid, + nullptr, + do_checkpoint, + nullptr); assert_zero(r); while (!checkpoint_callback_called) { - usleep(1*1024*1024); + usleep(1 * 1024 * 1024); } } } diff --git a/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-split.cc b/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-split.cc index 70c3ba22a0c..2b29de409b1 100644 --- a/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-split.cc +++ b/storage/tokudb/PerconaFT/ft/tests/test-checkpoint-during-split.cc @@ -113,10 +113,14 @@ static void flusher_callback(int state, void* extra) { if ((state == flt_flush_before_split && !after_split) || (state == flt_flush_during_split && after_split)) { checkpoint_called = true; - int r = toku_pthread_create(&checkpoint_tid, NULL, do_checkpoint, NULL); + int r = toku_pthread_create(toku_uninstrumented, + &checkpoint_tid, + nullptr, + do_checkpoint, + nullptr); assert_zero(r); while (!checkpoint_callback_called) { - usleep(1*1024*1024); + usleep(1 * 1024 * 1024); } } } diff --git a/storage/tokudb/PerconaFT/ft/tests/test3681.cc b/storage/tokudb/PerconaFT/ft/tests/test3681.cc index e5e24a88246..9e4a46e8dfe 100644 --- a/storage/tokudb/PerconaFT/ft/tests/test3681.cc +++ b/storage/tokudb/PerconaFT/ft/tests/test3681.cc @@ -91,13 +91,35 @@ static void *startb (void *n) { return NULL; } -static void test3681 (void) { +static void test3681(void) { setup(); - toku_pthread_t a,b; - { int r; r = toku_pthread_create(&a, NULL, starta, NULL); assert(r==0); } - { int r; r = toku_pthread_create(&b, NULL, startb, NULL); assert(r==0); } - { int r; void *v; r = toku_pthread_join(a, &v); assert(r==0); assert(v==NULL); } - { int r; void *v; r = toku_pthread_join(b, &v); assert(r==0); assert(v==NULL); } + toku_pthread_t a, b; + { + int r; + r = toku_pthread_create( + toku_uninstrumented, &a, nullptr, starta, nullptr); + assert(r == 0); + } + { + int r; + r = toku_pthread_create( + toku_uninstrumented, &b, nullptr, startb, nullptr); + assert(r == 0); + } + { + int r; + void *v; + r = toku_pthread_join(a, &v); + assert(r == 0); + assert(v == NULL); + } + { + int r; + void *v; + r = toku_pthread_join(b, &v); + assert(r == 0); + assert(v == NULL); + } finish(); } diff --git a/storage/tokudb/PerconaFT/ft/txn/roll.cc b/storage/tokudb/PerconaFT/ft/txn/roll.cc index 97afd2f5bdb..7228de06f34 100644 --- a/storage/tokudb/PerconaFT/ft/txn/roll.cc +++ b/storage/tokudb/PerconaFT/ft/txn/roll.cc @@ -195,14 +195,14 @@ int toku_rollback_frename(BYTESTRING old_iname, toku_cachetable_get_fname_in_cwd(cachetable, new_iname.data), &toku_free); - if (toku_stat(old_iname_full.get(), &stat) == -1) { + if (toku_stat(old_iname_full.get(), &stat, toku_uninstrumented) == -1) { if (ENOENT == errno) old_exist = false; else return 1; } - if (toku_stat(new_iname_full.get(), &stat) == -1) { + if (toku_stat(new_iname_full.get(), &stat, toku_uninstrumented) == -1) { if (ENOENT == errno || ENAMETOOLONG == errno) new_exist = false; else @@ -220,7 +220,7 @@ int toku_rollback_frename(BYTESTRING old_iname, // removed // and the new file is renamed. if (old_exist && new_exist && - (toku_os_unlink(old_iname_full.get()) == -1 || + (toku_os_delete(old_iname_full.get()) == -1 || toku_os_rename(new_iname_full.get(), old_iname_full.get()) == -1 || toku_fsync_directory(new_iname_full.get()) == -1 || toku_fsync_directory(old_iname_full.get()) == -1)) diff --git a/storage/tokudb/PerconaFT/ft/txn/rollback_log_node_cache.cc b/storage/tokudb/PerconaFT/ft/txn/rollback_log_node_cache.cc index 71b1e79277c..5e1ab746936 100644 --- a/storage/tokudb/PerconaFT/ft/txn/rollback_log_node_cache.cc +++ b/storage/tokudb/PerconaFT/ft/txn/rollback_log_node_cache.cc @@ -41,7 +41,9 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "txn/rollback_log_node_cache.h" -void rollback_log_node_cache::init (uint32_t max_num_avail_nodes) { +toku_instr_key* rollback_log_node_cache_mutex_key; + +void rollback_log_node_cache::init(uint32_t max_num_avail_nodes) { XMALLOC_N(max_num_avail_nodes, m_avail_blocknums); m_max_num_avail = max_num_avail_nodes; m_first = 0; @@ -49,7 +51,7 @@ void rollback_log_node_cache::init (uint32_t max_num_avail_nodes) { toku_pthread_mutexattr_t attr; toku_mutexattr_init(&attr); toku_mutexattr_settype(&attr, TOKU_MUTEX_ADAPTIVE); - toku_mutex_init(&m_mutex, &attr); + toku_mutex_init(*rollback_log_node_cache_mutex_key, &m_mutex, &attr); toku_mutexattr_destroy(&attr); } diff --git a/storage/tokudb/PerconaFT/ft/txn/txn.cc b/storage/tokudb/PerconaFT/ft/txn/txn.cc index a3ce6beb7b0..7327cbd9d24 100644 --- a/storage/tokudb/PerconaFT/ft/txn/txn.cc +++ b/storage/tokudb/PerconaFT/ft/txn/txn.cc @@ -45,8 +45,11 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "ft/txn/txn_manager.h" #include "util/status.h" -void -toku_txn_get_status(TXN_STATUS s) { +toku_instr_key *txn_lock_mutex_key; +toku_instr_key *txn_state_lock_mutex_key; +toku_instr_key *result_state_cond_key; + +void toku_txn_get_status(TXN_STATUS s) { txn_status.init(); *s = txn_status; } @@ -225,74 +228,74 @@ static void toku_txn_create_txn ( static txn_child_manager tcm; - struct tokutxn new_txn = { - .txnid = {.parent_id64 = TXNID_NONE, .child_id64 = TXNID_NONE }, - .snapshot_txnid64 = TXNID_NONE, - .snapshot_type = for_recovery ? TXN_SNAPSHOT_NONE : snapshot_type, - .for_recovery = for_recovery, - .logger = logger, - .parent = parent_tokutxn, - .child = NULL, - .child_manager_s = tcm, - .child_manager = NULL, - .container_db_txn = container_db_txn, - .live_root_txn_list = nullptr, - .xids = NULL, - .snapshot_next = NULL, - .snapshot_prev = NULL, - .begin_was_logged = false, - .declared_read_only = read_only, - .do_fsync = false, - .force_fsync_on_commit = false, - .do_fsync_lsn = ZERO_LSN, - .xa_xid = {0, 0, 0, ""}, - .progress_poll_fun = NULL, - .progress_poll_fun_extra = NULL, - - // You cannot initialize txn_lock a TOKU_MUTEX_INITIALIZER, because we - // will initialize it in the code below, and it cannot already - // be initialized at that point. Also, in general, you don't - // get to use PTHREAD_MUTEX_INITALIZER (which is what is inside - // TOKU_MUTEX_INITIALIZER) except in static variables, and this - // is initializing an auto variable. - // - // And we cannot simply avoid initializing these fields - // because, although it avoids -Wmissing-field-initializer - // errors under gcc, it gets other errors about non-trivial - // designated initializers not being supported. - - .txn_lock = ZERO_MUTEX_INITIALIZER, // Not TOKU_MUTEX_INITIALIZER - .open_fts = open_fts, - .roll_info = roll_info, - .state_lock = ZERO_MUTEX_INITIALIZER, // Not TOKU_MUTEX_INITIALIZER - .state_cond = ZERO_COND_INITIALIZER, // Not TOKU_COND_INITIALIZER - .state = TOKUTXN_LIVE, - .num_pin = 0, - .client_id = 0, - .client_extra = nullptr, - .start_time = time(NULL), - }; +struct tokutxn new_txn = { + .txnid = {.parent_id64 = TXNID_NONE, .child_id64 = TXNID_NONE }, + .snapshot_txnid64 = TXNID_NONE, + .snapshot_type = for_recovery ? TXN_SNAPSHOT_NONE : snapshot_type, + .for_recovery = for_recovery, + .logger = logger, + .parent = parent_tokutxn, + .child = NULL, + .child_manager_s = tcm, + .child_manager = NULL, + .container_db_txn = container_db_txn, + .live_root_txn_list = nullptr, + .xids = NULL, + .snapshot_next = NULL, + .snapshot_prev = NULL, + .begin_was_logged = false, + .declared_read_only = read_only, + .do_fsync = false, + .force_fsync_on_commit = false, + .do_fsync_lsn = ZERO_LSN, + .xa_xid = {0, 0, 0, ""}, + .progress_poll_fun = NULL, + .progress_poll_fun_extra = NULL, + + // You cannot initialize txn_lock a TOKU_MUTEX_INITIALIZER, because we + // will initialize it in the code below, and it cannot already + // be initialized at that point. Also, in general, you don't + // get to use PTHREAD_MUTEX_INITALIZER (which is what is inside + // TOKU_MUTEX_INITIALIZER) except in static variables, and this + // is initializing an auto variable. + // + // And we cannot simply avoid initializing these fields + // because, although it avoids -Wmissing-field-initializer + // errors under gcc, it gets other errors about non-trivial + // designated initializers not being supported. + + .txn_lock = ZERO_MUTEX_INITIALIZER, // Not TOKU_MUTEX_INITIALIZER + .open_fts = open_fts, + .roll_info = roll_info, + .state_lock = ZERO_MUTEX_INITIALIZER, // Not TOKU_MUTEX_INITIALIZER + .state_cond = ZERO_COND_INITIALIZER, // Not TOKU_COND_INITIALIZER + .state = TOKUTXN_LIVE, + .num_pin = 0, + .client_id = 0, + .client_extra = nullptr, + .start_time = time(NULL), +}; - TOKUTXN result = NULL; - XMEMDUP(result, &new_txn); - invalidate_xa_xid(&result->xa_xid); - if (parent_tokutxn == NULL) { - result->child_manager = &result->child_manager_s; - result->child_manager->init(result); +TOKUTXN result = NULL; +XMEMDUP(result, &new_txn); +invalidate_xa_xid(&result->xa_xid); +if (parent_tokutxn == NULL) { + result->child_manager = &result->child_manager_s; + result->child_manager->init(result); } else { result->child_manager = parent_tokutxn->child_manager; } - toku_mutex_init(&result->txn_lock, nullptr); + toku_mutex_init(*txn_lock_mutex_key, &result->txn_lock, nullptr); toku_pthread_mutexattr_t attr; toku_mutexattr_init(&attr); toku_mutexattr_settype(&attr, TOKU_MUTEX_ADAPTIVE); - toku_mutex_init(&result->state_lock, &attr); + toku_mutex_init(*txn_state_lock_mutex_key, &result->state_lock, &attr); toku_mutexattr_destroy(&attr); - toku_cond_init(&result->state_cond, nullptr); + toku_cond_init(*result_state_cond_key, &result->state_cond, nullptr); *tokutxn = result; diff --git a/storage/tokudb/PerconaFT/ft/txn/txn_child_manager.cc b/storage/tokudb/PerconaFT/ft/txn/txn_child_manager.cc index db110127c55..99a21331b0a 100644 --- a/storage/tokudb/PerconaFT/ft/txn/txn_child_manager.cc +++ b/storage/tokudb/PerconaFT/ft/txn/txn_child_manager.cc @@ -39,6 +39,8 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "ft/logger/log-internal.h" #include "ft/txn/txn_child_manager.h" +toku_instr_key *txn_child_manager_mutex_key; + // // initialized a txn_child_manager, // when called, root->txnid.parent_id64 may not yet be set @@ -53,7 +55,7 @@ void txn_child_manager::init(TOKUTXN root) { toku_pthread_mutexattr_t attr; toku_mutexattr_init(&attr); toku_mutexattr_settype(&attr, TOKU_MUTEX_ADAPTIVE); - toku_mutex_init(&m_mutex, &attr); + toku_mutex_init(*txn_child_manager_mutex_key, &m_mutex, &attr); toku_mutexattr_destroy(&attr); } diff --git a/storage/tokudb/PerconaFT/ft/txn/txn_manager.cc b/storage/tokudb/PerconaFT/ft/txn/txn_manager.cc index 8fe52b10597..1b55844bc7d 100644 --- a/storage/tokudb/PerconaFT/ft/txn/txn_manager.cc +++ b/storage/tokudb/PerconaFT/ft/txn/txn_manager.cc @@ -56,7 +56,10 @@ void set_test_txn_sync_callback(void (*cb) (pthread_t, void *), void *extra) { } bool garbage_collection_debug = false; -static bool txn_records_snapshot(TXN_SNAPSHOT_TYPE snapshot_type, struct tokutxn *parent) { +toku_instr_key *txn_manager_lock_mutex_key; + +static bool txn_records_snapshot(TXN_SNAPSHOT_TYPE snapshot_type, + struct tokutxn *parent) { if (snapshot_type == TXN_COPIES_SNAPSHOT) { return false; } @@ -248,9 +251,10 @@ verify_snapshot_system(TXN_MANAGER txn_manager UU()) { live_root_txns_omt.destroy(); } -void toku_txn_manager_init(TXN_MANAGER* txn_managerp) { +void toku_txn_manager_init(TXN_MANAGER *txn_managerp) { TXN_MANAGER XCALLOC(txn_manager); - toku_mutex_init(&txn_manager->txn_manager_lock, NULL); + toku_mutex_init( + *txn_manager_lock_mutex_key, &txn_manager->txn_manager_lock, nullptr); txn_manager->live_root_txns.create(); txn_manager->live_root_ids.create(); txn_manager->snapshot_head = NULL; diff --git a/storage/tokudb/PerconaFT/locktree/lock_request.cc b/storage/tokudb/PerconaFT/locktree/lock_request.cc index 0151b5bd466..c0829e3f4e1 100644 --- a/storage/tokudb/PerconaFT/locktree/lock_request.cc +++ b/storage/tokudb/PerconaFT/locktree/lock_request.cc @@ -62,7 +62,7 @@ void lock_request::create(void) { m_state = state::UNINITIALIZED; m_info = nullptr; - toku_cond_init(&m_wait_cond, nullptr); + toku_cond_init(*lock_request_m_wait_cond_key, &m_wait_cond, nullptr); m_start_test_callback = nullptr; m_start_before_pending_test_callback = nullptr; diff --git a/storage/tokudb/PerconaFT/locktree/locktree.cc b/storage/tokudb/PerconaFT/locktree/locktree.cc index 2fbf078bdd6..069aae26f66 100644 --- a/storage/tokudb/PerconaFT/locktree/locktree.cc +++ b/storage/tokudb/PerconaFT/locktree/locktree.cc @@ -51,7 +51,6 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. // the locktree source file instead of the header. #include "concurrent_tree.h" - namespace toku { // A locktree represents the set of row locks owned by all transactions @@ -87,12 +86,13 @@ void lt_lock_request_info::init(void) { pending_lock_requests.create(); pending_is_empty = true; ZERO_STRUCT(mutex); - toku_mutex_init(&mutex, nullptr); + toku_mutex_init(*locktree_request_info_mutex_key, &mutex, nullptr); retry_want = retry_done = 0; ZERO_STRUCT(counters); ZERO_STRUCT(retry_mutex); - toku_mutex_init(&retry_mutex, nullptr); - toku_cond_init(&retry_cv, nullptr); + toku_mutex_init( + *locktree_request_info_retry_mutex_key, &retry_mutex, nullptr); + toku_cond_init(*locktree_request_info_retry_cv_key, &retry_cv, nullptr); running_retry = false; TOKU_VALGRIND_HG_DISABLE_CHECKING(&pending_is_empty, diff --git a/storage/tokudb/PerconaFT/locktree/manager.cc b/storage/tokudb/PerconaFT/locktree/manager.cc index 91ff7c5a007..6bb5c77bf32 100644 --- a/storage/tokudb/PerconaFT/locktree/manager.cc +++ b/storage/tokudb/PerconaFT/locktree/manager.cc @@ -56,9 +56,8 @@ void locktree_manager::create(lt_create_cb create_cb, lt_destroy_cb destroy_cb, m_lt_destroy_callback = destroy_cb; m_lt_escalate_callback = escalate_cb; m_lt_escalate_callback_extra = escalate_extra; - ZERO_STRUCT(m_mutex); - toku_mutex_init(&m_mutex, nullptr); + toku_mutex_init(*manager_mutex_key, &m_mutex, nullptr); ZERO_STRUCT(m_lt_counters); @@ -346,7 +345,8 @@ int locktree_manager::check_current_lock_constraints(bool big_txn) { void locktree_manager::escalator_init(void) { ZERO_STRUCT(m_escalation_mutex); - toku_mutex_init(&m_escalation_mutex, nullptr); + toku_mutex_init( + *manager_escalation_mutex_key, &m_escalation_mutex, nullptr); m_escalation_count = 0; m_escalation_time = 0; m_wait_escalation_count = 0; @@ -403,8 +403,8 @@ struct escalate_args { void locktree_manager::locktree_escalator::create(void) { ZERO_STRUCT(m_escalator_mutex); - toku_mutex_init(&m_escalator_mutex, nullptr); - toku_cond_init(&m_escalator_done, nullptr); + toku_mutex_init(*manager_escalator_mutex_key, &m_escalator_mutex, nullptr); + toku_cond_init(*manager_m_escalator_done_key, &m_escalator_done, nullptr); m_escalator_running = false; } diff --git a/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_1big7lt_1small.cc b/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_1big7lt_1small.cc index 6c143f963ba..32029b5bddd 100644 --- a/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_1big7lt_1small.cc +++ b/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_1big7lt_1small.cc @@ -201,12 +201,14 @@ int main(int argc, const char *argv[]) { locktree *small_lt = mgr.get_lt(dict_id, dbt_comparator, nullptr); // create the worker threads - struct big_arg big_arg = { &mgr, big_lt, n_big, 1000 }; - r = toku_pthread_create(&big_id, nullptr, big_f, &big_arg); + struct big_arg big_arg = {&mgr, big_lt, n_big, 1000}; + r = toku_pthread_create( + toku_uninstrumented, &big_id, nullptr, big_f, &big_arg); assert(r == 0); - struct small_arg small_arg = { &mgr, small_lt, 2000, 0 }; - r = toku_pthread_create(&small_id, nullptr, small_f, &small_arg); + struct small_arg small_arg = {&mgr, small_lt, 2000, 0}; + r = toku_pthread_create( + toku_uninstrumented, &small_id, nullptr, small_f, &small_arg); assert(r == 0); // wait for some escalations to occur diff --git a/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_2big_1lt.cc b/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_2big_1lt.cc index 17eb07060d4..ff59a7bdd5c 100644 --- a/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_2big_1lt.cc +++ b/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_2big_1lt.cc @@ -169,8 +169,10 @@ int main(int argc, const char *argv[]) { struct arg big_arg[n_big]; pthread_t big_ids[n_big]; for (int i = 0; i < n_big; i++) { - big_arg[i] = { &mgr, lt[i % n_lt], (TXNID)(1000+i), i == 0 ? 1 : -1000000000 }; - r = toku_pthread_create(&big_ids[i], nullptr, big_f, &big_arg[i]); + big_arg[i] = { + &mgr, lt[i % n_lt], (TXNID)(1000 + i), i == 0 ? 1 : -1000000000}; + r = toku_pthread_create( + toku_uninstrumented, &big_ids[i], nullptr, big_f, &big_arg[i]); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_2big_2lt.cc b/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_2big_2lt.cc index 4326e8fafc2..be1ddaba9d0 100644 --- a/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_2big_2lt.cc +++ b/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_2big_2lt.cc @@ -169,8 +169,10 @@ int main(int argc, const char *argv[]) { struct arg big_arg[n_big]; pthread_t big_ids[n_big]; for (int i = 0; i < n_big; i++) { - big_arg[i] = { &mgr, lt[i % n_lt], (TXNID)(1000+i), i == 0 ? 1 : -1000000000 }; - r = toku_pthread_create(&big_ids[i], nullptr, big_f, &big_arg[i]); + big_arg[i] = { + &mgr, lt[i % n_lt], (TXNID)(1000 + i), i == 0 ? 1 : -1000000000}; + r = toku_pthread_create( + toku_uninstrumented, &big_ids[i], nullptr, big_f, &big_arg[i]); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_stalls.cc b/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_stalls.cc index d146d94e337..9dc9596a7ed 100644 --- a/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_stalls.cc +++ b/storage/tokudb/PerconaFT/locktree/tests/locktree_escalation_stalls.cc @@ -182,9 +182,10 @@ int main(int argc, const char *argv[]) { locktree *lt_1 = mgr.get_lt(dict_id_1, dbt_comparator, nullptr); // create the worker threads - struct arg big_arg = { &mgr, lt_0, 1000 }; + struct arg big_arg = {&mgr, lt_0, 1000}; pthread_t big_id; - r = toku_pthread_create(&big_id, nullptr, big_f, &big_arg); + r = toku_pthread_create( + toku_uninstrumented, &big_id, nullptr, big_f, &big_arg); assert(r == 0); const int n_small = 7; @@ -192,8 +193,12 @@ int main(int argc, const char *argv[]) { struct arg small_args[n_small]; for (int i = 0; i < n_small; i++) { - small_args[i] = { &mgr, lt_1, (TXNID)(2000+i), i }; - r = toku_pthread_create(&small_ids[i], nullptr, small_f, &small_args[i]); + small_args[i] = {&mgr, lt_1, (TXNID)(2000 + i), i}; + r = toku_pthread_create(toku_uninstrumented, + &small_ids[i], + nullptr, + small_f, + &small_args[i]); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/locktree/tests/manager_parallel_locktree_get_release.cc b/storage/tokudb/PerconaFT/locktree/tests/manager_parallel_locktree_get_release.cc index ec9ef21583c..08ce63140a5 100644 --- a/storage/tokudb/PerconaFT/locktree/tests/manager_parallel_locktree_get_release.cc +++ b/storage/tokudb/PerconaFT/locktree/tests/manager_parallel_locktree_get_release.cc @@ -71,7 +71,8 @@ void manager_unit_test::test_reference_release_lt(void) { const int nthreads = 2; pthread_t ids[nthreads]; for (int i = 0; i < nthreads; i++) { - r = toku_pthread_create(&ids[i], nullptr, my_tester, &mgr); + r = toku_pthread_create( + toku_uninstrumented, &ids[i], nullptr, my_tester, &mgr); assert(r == 0); } for (int i = 0; i < nthreads; i++) { diff --git a/storage/tokudb/PerconaFT/locktree/treenode.cc b/storage/tokudb/PerconaFT/locktree/treenode.cc index 4f43291fe76..cc3a4969643 100644 --- a/storage/tokudb/PerconaFT/locktree/treenode.cc +++ b/storage/tokudb/PerconaFT/locktree/treenode.cc @@ -38,9 +38,9 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include <toku_race_tools.h> -void treenode::mutex_lock(void) { - toku_mutex_lock(&m_mutex); -} +// TODO: source location info might have to be pulled up one caller +// to be useful +void treenode::mutex_lock(void) { toku_mutex_lock(&m_mutex); } void treenode::mutex_unlock(void) { toku_mutex_unlock(&m_mutex); @@ -58,7 +58,7 @@ void treenode::init(const comparator *cmp) { toku_pthread_mutexattr_t attr; toku_mutexattr_init(&attr); toku_mutexattr_settype(&attr, TOKU_MUTEX_ADAPTIVE); - toku_mutex_init(&m_mutex, &attr); + toku_mutex_init(*treenode_mutex_key, &m_mutex, &attr); toku_mutexattr_destroy(&attr); m_left_child.set(nullptr); m_right_child.set(nullptr); diff --git a/storage/tokudb/PerconaFT/portability/CMakeLists.txt b/storage/tokudb/PerconaFT/portability/CMakeLists.txt index 4793db63cc1..e5576a5d463 100644 --- a/storage/tokudb/PerconaFT/portability/CMakeLists.txt +++ b/storage/tokudb/PerconaFT/portability/CMakeLists.txt @@ -8,6 +8,7 @@ set(tokuportability_srcs portability toku_assert toku_crash + toku_instr_mysql toku_path toku_pthread toku_time @@ -53,6 +54,10 @@ if (NOT DEFINED MYSQL_PROJECT_NAME_DOCSTRING) DESTINATION ${INSTALL_LIBDIR} COMPONENT tokukv_libs_shared ) +else () + set_property(SOURCE toku_pthread portability APPEND PROPERTY + COMPILE_DEFINITIONS MYSQL_TOKUDB_ENGINE=1 ) + target_link_libraries(${LIBTOKUPORTABILITY} LINK_PRIVATE mysys) endif () add_subdirectory(tests) diff --git a/storage/tokudb/PerconaFT/portability/file.cc b/storage/tokudb/PerconaFT/portability/file.cc index 0e3efc1a12a..485bfac8514 100644 --- a/storage/tokudb/PerconaFT/portability/file.cc +++ b/storage/tokudb/PerconaFT/portability/file.cc @@ -52,9 +52,12 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "toku_path.h" #include <portability/toku_atomic.h> +toku_instr_key *tokudb_file_data_key; + static int toku_assert_on_write_enospc = 0; static const int toku_write_enospc_sleep = 1; -static uint64_t toku_write_enospc_last_report; // timestamp of most recent report to error log +static uint64_t toku_write_enospc_last_report; // timestamp of most recent + // report to error log static time_t toku_write_enospc_last_time; // timestamp of most recent ENOSPC static uint32_t toku_write_enospc_current; // number of threads currently blocked on ENOSPC static uint64_t toku_write_enospc_total; // total number of times ENOSPC was returned from an attempt to write @@ -142,11 +145,17 @@ static ssize_t (*t_full_pwrite)(int, const void *, size_t, off_t); static FILE * (*t_fdopen)(int, const char *); static FILE * (*t_fopen)(const char *, const char *); static int (*t_open)(const char *, int, int); -static int (*t_fclose)(FILE *); +static int (*t_fclose)(FILE *); static ssize_t (*t_read)(int, void *, size_t); static ssize_t (*t_pread)(int, void *, size_t, off_t); +static size_t (*os_fwrite_fun)(const void *, size_t, size_t, FILE *) = nullptr; + +void toku_set_func_fwrite( + size_t (*fwrite_fun)(const void *, size_t, size_t, FILE *)) { + os_fwrite_fun = fwrite_fun; +} -void toku_set_func_write (ssize_t (*write_fun)(int, const void *, size_t)) { +void toku_set_func_write(ssize_t (*write_fun)(int, const void *, size_t)) { t_write = write_fun; } @@ -186,9 +195,63 @@ void toku_set_func_pread (ssize_t (*pread_fun)(int, void *, size_t, off_t)) { t_pread = pread_fun; } -void -toku_os_full_write (int fd, const void *buf, size_t len) { - const char *bp = (const char *) buf; +int toku_os_delete_with_source_location(const char *name, + const char *src_file, + uint src_line) { + + toku_io_instrumentation io_annotation; + toku_instr_file_name_close_begin(io_annotation, + *tokudb_file_data_key, + toku_instr_file_op::file_delete, + name, + src_file, + src_line); + const int result = unlink(name); + + /* Register the result value with the instrumentation system */ + toku_instr_file_close_end(io_annotation, result); + + return result; +} + +int toku_os_rename_with_source_location(const char *old_name, + const char *new_name, + const char *src_file, + uint src_line) { + int result; + + toku_io_instrumentation io_annotation; + toku_instr_file_name_io_begin(io_annotation, + *tokudb_file_data_key, + toku_instr_file_op::file_rename, + new_name, + 0, + src_file, + src_line); + + result = rename(old_name, new_name); + /* Regsiter the result value with the instrumentation system */ + toku_instr_file_io_end(io_annotation, 0); + + return result; +} + +void toku_os_full_write_with_source_location(int fd, + const void *buf, + size_t len, + const char *src_file, + uint src_line) { + const char *bp = (const char *)buf; + size_t bytes_written = len; + + toku_io_instrumentation io_annotation; + toku_instr_file_io_begin(io_annotation, + toku_instr_file_op::file_write, + fd, + len, + src_file, + src_line); + while (len > 0) { ssize_t r; if (t_full_write) { @@ -205,14 +268,30 @@ toku_os_full_write (int fd, const void *buf, size_t len) { } } assert(len == 0); + + /* Register the result value with the instrumentaion system */ + toku_instr_file_io_end(io_annotation, bytes_written); } -int -toku_os_write (int fd, const void *buf, size_t len) { - const char *bp = (const char *) buf; +int toku_os_write_with_source_location(int fd, + const void *buf, + size_t len, + const char *src_file, + uint src_line) { + const char *bp = (const char *)buf; int result = 0; + ssize_t r; + + size_t bytes_written = len; + toku_io_instrumentation io_annotation; + toku_instr_file_io_begin(io_annotation, + toku_instr_file_op::file_write, + fd, + len, + src_file, + src_line); + while (len > 0) { - ssize_t r; if (t_write) { r = t_write(fd, bp, len); } else { @@ -222,17 +301,33 @@ toku_os_write (int fd, const void *buf, size_t len) { result = errno; break; } - len -= r; - bp += r; + len -= r; + bp += r; } + /* Register the result value with the instrumentation system */ + toku_instr_file_io_end(io_annotation, bytes_written - len); + return result; } -void -toku_os_full_pwrite (int fd, const void *buf, size_t len, toku_off_t off) { - assert(0==((long long)buf)%512); - assert((len%512 == 0) && (off%512)==0); // to make pwrite work. - const char *bp = (const char *) buf; +void toku_os_full_pwrite_with_source_location(int fd, + const void *buf, + size_t len, + toku_off_t off, + const char *src_file, + uint src_line) { + assert(0 == ((long long)buf) % 512); + assert((len % 512 == 0) && (off % 512) == 0); // to make pwrite work. + const char *bp = (const char *)buf; + + size_t bytes_written = len; + toku_io_instrumentation io_annotation; + toku_instr_file_io_begin(io_annotation, + toku_instr_file_op::file_write, + fd, + len, + src_file, + src_line); while (len > 0) { ssize_t r; if (t_full_pwrite) { @@ -250,71 +345,209 @@ toku_os_full_pwrite (int fd, const void *buf, size_t len, toku_off_t off) { } } assert(len == 0); -} -ssize_t -toku_os_pwrite (int fd, const void *buf, size_t len, toku_off_t off) { - assert(0==((long long)buf)%512); // these asserts are to ensure that direct I/O will work. - assert(0==len %512); - assert(0==off %512); - const char *bp = (const char *) buf; + /* Register the result value with the instrumentation system */ + toku_instr_file_io_end(io_annotation, bytes_written); +} + +ssize_t toku_os_pwrite_with_source_location(int fd, + const void *buf, + size_t len, + toku_off_t off, + const char *src_file, + uint src_line) { + assert(0 == + ((long long)buf) % + 512); // these asserts are to ensure that direct I/O will work. + assert(0 == len % 512); + assert(0 == off % 512); + const char *bp = (const char *)buf; ssize_t result = 0; + ssize_t r; + + size_t bytes_written = len; + toku_io_instrumentation io_annotation; + toku_instr_file_io_begin(io_annotation, + toku_instr_file_op::file_write, + fd, + len, + src_file, + src_line); while (len > 0) { - ssize_t r; - if (t_pwrite) { - r = t_pwrite(fd, bp, len, off); - } else { - r = pwrite(fd, bp, len, off); - } + r = (t_pwrite) ? t_pwrite(fd, bp, len, off) : pwrite(fd, bp, len, off); + if (r < 0) { result = errno; break; } len -= r; - bp += r; - off += r; + bp += r; + off += r; + } + /* Register the result value with the instrumentation system */ + toku_instr_file_io_end(io_annotation, bytes_written - len); + + return result; +} + +int toku_os_fwrite_with_source_location(const void *ptr, + size_t size, + size_t nmemb, + TOKU_FILE *stream, + const char *src_file, + uint src_line) { + int result = 0; + size_t bytes_written; + + toku_io_instrumentation io_annotation; + toku_instr_file_stream_io_begin(io_annotation, + toku_instr_file_op::file_write, + *stream, + nmemb, + src_file, + src_line); + + if (os_fwrite_fun) { + bytes_written = os_fwrite_fun(ptr, size, nmemb, stream->file); + } else { + bytes_written = fwrite(ptr, size, nmemb, stream->file); + } + + if (bytes_written != nmemb) { + if (os_fwrite_fun) // if using hook to induce artificial errors (for + // testing) ... + result = get_maybe_error_errno(); // ... then there is no error in + // the stream, but there is one + // in errno + else + result = ferror(stream->file); + invariant(result != 0); // Should we assert here? + } + /* Register the result value with the instrumentation system */ + toku_instr_file_io_end(io_annotation, bytes_written); + + return result; +} + +int toku_os_fread_with_source_location(void *ptr, + size_t size, + size_t nmemb, + TOKU_FILE *stream, + const char *src_file, + uint src_line) { + int result = 0; + size_t bytes_read; + + toku_io_instrumentation io_annotation; + toku_instr_file_stream_io_begin(io_annotation, + toku_instr_file_op::file_read, + *stream, + nmemb, + src_file, + src_line); + + if ((bytes_read = fread(ptr, size, nmemb, stream->file)) != nmemb) { + if ((feof(stream->file))) + result = EOF; + else + result = ferror(stream->file); + invariant(result != 0); // Should we assert here? } + /* Register the result value with the instrumentation system */ + toku_instr_file_io_end(io_annotation, bytes_read); + return result; } -FILE * -toku_os_fdopen(int fildes, const char *mode) { - FILE * rval; - if (t_fdopen) - rval = t_fdopen(fildes, mode); - else - rval = fdopen(fildes, mode); +TOKU_FILE *toku_os_fdopen_with_source_location(int fildes, + const char *mode, + const char *filename, + const toku_instr_key &instr_key, + const char *src_file, + uint src_line) { + TOKU_FILE *XMALLOC(rval); + if (FT_LIKELY(rval != nullptr)) { + toku_io_instrumentation io_annotation; + toku_instr_file_open_begin(io_annotation, + instr_key, + toku_instr_file_op::file_stream_open, + filename, + src_file, + src_line); + + rval->file = (t_fdopen) ? t_fdopen(fildes, mode) : fdopen(fildes, mode); + toku_instr_file_stream_open_end(io_annotation, *rval); + + if (FT_UNLIKELY(rval->file == nullptr)) { + toku_free(rval); + rval = nullptr; + } + } return rval; } - -FILE * -toku_os_fopen(const char *filename, const char *mode){ - FILE * rval; - if (t_fopen) - rval = t_fopen(filename, mode); - else - rval = fopen(filename, mode); +TOKU_FILE *toku_os_fopen_with_source_location(const char *filename, + const char *mode, + const toku_instr_key &instr_key, + const char *src_file, + uint src_line) { + TOKU_FILE *XMALLOC(rval); + if (FT_UNLIKELY(rval == nullptr)) + return nullptr; + + toku_io_instrumentation io_annotation; + toku_instr_file_open_begin(io_annotation, + instr_key, + toku_instr_file_op::file_stream_open, + filename, + src_file, + src_line); + rval->file = t_fopen ? t_fopen(filename, mode) : fopen(filename, mode); + /* Register the returning "file" value with the system */ + toku_instr_file_stream_open_end(io_annotation, *rval); + + if (FT_UNLIKELY(rval->file == nullptr)) { + toku_free(rval); + rval = nullptr; + } return rval; } -int -toku_os_open(const char *path, int oflag, int mode) { - int rval; +int toku_os_open_with_source_location(const char *path, + int oflag, + int mode, + const toku_instr_key &instr_key, + const char *src_file, + uint src_line) { + int fd; + toku_io_instrumentation io_annotation; + /* register a file open or creation depending on "oflag" */ + toku_instr_file_open_begin( + io_annotation, + instr_key, + ((oflag & O_CREAT) ? toku_instr_file_op::file_create + : toku_instr_file_op::file_open), + path, + src_file, + src_line); if (t_open) - rval = t_open(path, oflag, mode); + fd = t_open(path, oflag, mode); else - rval = open(path, oflag, mode); - return rval; + fd = open(path, oflag, mode); + + toku_instr_file_open_end(io_annotation, fd); + return fd; } -int -toku_os_open_direct(const char *path, int oflag, int mode) { +int toku_os_open_direct(const char *path, + int oflag, + int mode, + const toku_instr_key &instr_key) { int rval; #if defined(HAVE_O_DIRECT) - rval = toku_os_open(path, oflag | O_DIRECT, mode); + rval = toku_os_open(path, oflag | O_DIRECT, mode, instr_key); #elif defined(HAVE_F_NOCACHE) - rval = toku_os_open(path, oflag, mode); + rval = toku_os_open(path, oflag, mode, instr_key); if (rval >= 0) { int r = fcntl(rval, F_NOCACHE, 1); if (r == -1) { @@ -327,63 +560,112 @@ toku_os_open_direct(const char *path, int oflag, int mode) { return rval; } -int -toku_os_fclose(FILE * stream) { +int toku_os_fclose_with_source_location(TOKU_FILE *stream, + const char *src_file, + uint src_line) { int rval = -1; - if (t_fclose) - rval = t_fclose(stream); - else { // if EINTR, retry until success - while (rval != 0) { - rval = fclose(stream); - if (rval && (errno != EINTR)) - break; - } + if (FT_LIKELY(stream != nullptr)) { + /* register a file stream close " */ + toku_io_instrumentation io_annotation; + toku_instr_file_stream_close_begin( + io_annotation, + toku_instr_file_op::file_stream_close, + *stream, + src_file, + src_line); + + if (t_fclose) + rval = t_fclose(stream->file); + else { // if EINTR, retry until success + while (rval != 0) { + rval = fclose(stream->file); + if (rval && (errno != EINTR)) + break; + } + } + /* Register the returning "rval" value with the system */ + toku_instr_file_close_end(io_annotation, rval); + toku_free(stream); + stream = nullptr; } return rval; } -int -toku_os_close(int fd) { // if EINTR, retry until success +int toku_os_close_with_source_location( + int fd, + const char *src_file, + uint src_line) { // if EINTR, retry until success + /* register the file close */ int r = -1; + + /* register a file descriptor close " */ + toku_io_instrumentation io_annotation; + toku_instr_file_fd_close_begin( + io_annotation, toku_instr_file_op::file_close, fd, src_file, src_line); while (r != 0) { - r = close(fd); - if (r) { - int rr = errno; - if (rr!=EINTR) printf("rr=%d (%s)\n", rr, strerror(rr)); - assert(rr==EINTR); - } + r = close(fd); + if (r) { + int rr = errno; + if (rr != EINTR) + printf("rr=%d (%s)\n", rr, strerror(rr)); + assert(rr == EINTR); + } } - return r; -} - -int toku_os_rename(const char *old_name, const char *new_name) { - return rename(old_name, new_name); -} -int toku_os_unlink(const char *path) { return unlink(path); } + /* Regsiter the returning value with the system */ + toku_instr_file_close_end(io_annotation, r); -ssize_t -toku_os_read(int fd, void *buf, size_t count) { - ssize_t r; - if (t_read) - r = t_read(fd, buf, count); - else - r = read(fd, buf, count); return r; } -ssize_t -toku_os_pread (int fd, void *buf, size_t count, off_t offset) { - assert(0==((long long)buf)%512); - assert(0==count%512); - assert(0==offset%512); - ssize_t r; +ssize_t toku_os_read_with_source_location(int fd, + void *buf, + size_t count, + const char *src_file, + uint src_line) { + ssize_t bytes_read; + + toku_io_instrumentation io_annotation; + toku_instr_file_io_begin(io_annotation, + toku_instr_file_op::file_read, + fd, + count, + src_file, + src_line); + + bytes_read = (t_read) ? t_read(fd, buf, count) : read(fd, buf, count); + + toku_instr_file_io_end(io_annotation, bytes_read); + + return bytes_read; +} + +ssize_t inline_toku_os_pread_with_source_location(int fd, + void *buf, + size_t count, + off_t offset, + const char *src_file, + uint src_line) { + assert(0 == ((long long)buf) % 512); + assert(0 == count % 512); + assert(0 == offset % 512); + ssize_t bytes_read; + + toku_io_instrumentation io_annotation; + toku_instr_file_io_begin(io_annotation, + toku_instr_file_op::file_read, + fd, + count, + src_file, + src_line); if (t_pread) { - r = t_pread(fd, buf, count, offset); + bytes_read = t_pread(fd, buf, count, offset); } else { - r = pread(fd, buf, count, offset); + bytes_read = pread(fd, buf, count, offset); } - return r; + toku_instr_file_io_end(io_annotation, bytes_read); + + return bytes_read; } void toku_os_recursive_delete(const char *path) { @@ -411,13 +693,24 @@ void toku_set_func_fsync(int (*fsync_function)(int)) { } // keep trying if fsync fails because of EINTR -static void file_fsync_internal (int fd) { +void file_fsync_internal_with_source_location(int fd, + const char *src_file, + uint src_line) { uint64_t tstart = toku_current_time_microsec(); int r = -1; uint64_t eintr_count = 0; + + toku_io_instrumentation io_annotation; + toku_instr_file_io_begin(io_annotation, + toku_instr_file_op::file_sync, + fd, + 0, + src_file, + src_line); + while (r != 0) { - if (t_fsync) { - r = t_fsync(fd); + if (t_fsync) { + r = t_fsync(fd); } else { r = fsync(fd); } @@ -429,6 +722,9 @@ static void file_fsync_internal (int fd) { toku_sync_fetch_and_add(&toku_fsync_count, 1); uint64_t duration = toku_current_time_microsec() - tstart; toku_sync_fetch_and_add(&toku_fsync_time, duration); + + toku_instr_file_io_end(io_annotation, 0); + if (duration >= toku_long_fsync_threshold) { toku_sync_fetch_and_add(&toku_long_fsync_count, 1); toku_sync_fetch_and_add(&toku_long_fsync_time, duration); diff --git a/storage/tokudb/PerconaFT/portability/memory.cc b/storage/tokudb/PerconaFT/portability/memory.cc index 5430ff84b70..9594158cf38 100644 --- a/storage/tokudb/PerconaFT/portability/memory.cc +++ b/storage/tokudb/PerconaFT/portability/memory.cc @@ -104,7 +104,13 @@ toku_memory_startup(void) { size_t lg_chunk; // log2 of the mmap threshold size_t lg_chunk_length = sizeof lg_chunk; result = mallctl_f("opt.lg_chunk", &lg_chunk, &lg_chunk_length, NULL, 0); - if (result == 0) + if (result) + { + status.mmap_threshold = 1 << 21; // Default value. + // Incompatible jemalloc change. + result = 0; + } + else status.mmap_threshold = 1 << lg_chunk; } } diff --git a/storage/tokudb/PerconaFT/portability/portability.cc b/storage/tokudb/PerconaFT/portability/portability.cc index 19f445a85d7..dfa5153cc66 100644 --- a/storage/tokudb/PerconaFT/portability/portability.cc +++ b/storage/tokudb/PerconaFT/portability/portability.cc @@ -79,6 +79,9 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "toku_os.h" #include "toku_time.h" #include "memory.h" + +#include "toku_instrumentation.h" + #include <portability/toku_atomic.h> #include <util/partitioned_counter.h> @@ -172,13 +175,26 @@ toku_os_get_phys_memory_size(void) { #endif } -int -toku_os_get_file_size(int fildes, int64_t *fsize) { +int toku_os_get_file_size_with_source_location(int fildes, + int64_t *fsize, + const char *src_file, + uint src_line) { toku_struct_stat sbuf; + + toku_io_instrumentation io_annotation; + toku_instr_file_io_begin(io_annotation, + toku_instr_file_op::file_stat, + fildes, + 0, + src_file, + src_line); + int r = fstat(fildes, &sbuf); - if (r==0) { + if (r == 0) { *fsize = sbuf.st_size; } + toku_instr_file_io_end(io_annotation, 0); + return r; } @@ -272,15 +288,39 @@ toku_os_get_max_process_data_size(uint64_t *maxdata) { return r; } -int -toku_stat(const char *name, toku_struct_stat *buf) { +int toku_stat_with_source_location(const char *name, + toku_struct_stat *buf, + const toku_instr_key &instr_key, + const char *src_file, + uint src_line) { + toku_io_instrumentation io_annotation; + toku_instr_file_name_io_begin(io_annotation, + instr_key, + toku_instr_file_op::file_stat, + name, + 0, + src_file, + src_line); int r = stat(name, buf); + + toku_instr_file_io_end(io_annotation, 0); return r; } -int -toku_fstat(int fd, toku_struct_stat *buf) { +int toku_os_fstat_with_source_location(int fd, + toku_struct_stat *buf, + const char *src_file, + uint src_line) { + toku_io_instrumentation io_annotation; + toku_instr_file_io_begin(io_annotation, + toku_instr_file_op::file_stat, + fd, + 0, + src_file, + src_line); + int r = fstat(fd, buf); + toku_instr_file_io_end(io_annotation, 0); return r; } @@ -427,5 +467,9 @@ void __attribute__((constructor)) toku_portability_helgrind_ignore(void); void toku_portability_helgrind_ignore(void) { TOKU_VALGRIND_HG_DISABLE_CHECKING(&toku_cached_hz, sizeof toku_cached_hz); - TOKU_VALGRIND_HG_DISABLE_CHECKING(&toku_cached_pagesize, sizeof toku_cached_pagesize); + TOKU_VALGRIND_HG_DISABLE_CHECKING(&toku_cached_pagesize, + sizeof toku_cached_pagesize); } + +static const pfs_key_t pfs_not_instrumented = 0xFFFFFFFF; +toku_instr_key toku_uninstrumented(pfs_not_instrumented); diff --git a/storage/tokudb/PerconaFT/portability/tests/rwlock_condvar.h b/storage/tokudb/PerconaFT/portability/tests/rwlock_condvar.h index 92f2fb354f7..d1ebc81e1dc 100644 --- a/storage/tokudb/PerconaFT/portability/tests/rwlock_condvar.h +++ b/storage/tokudb/PerconaFT/portability/tests/rwlock_condvar.h @@ -107,10 +107,10 @@ get_waitstate(void) #endif int toku_cv_fair_rwlock_init (toku_cv_fair_rwlock_t *rwlock) { - rwlock->state=0; + rwlock->state = 0; rwlock->waiters_head = NULL; rwlock->waiters_tail = NULL; - toku_mutex_init(&rwlock->mutex, NULL); + toku_mutex_init(toku_uninstrumented, &rwlock->mutex, nullptr); return 0; } diff --git a/storage/tokudb/PerconaFT/portability/tests/test-pthread-rwlock-rdlock.cc b/storage/tokudb/PerconaFT/portability/tests/test-pthread-rwlock-rdlock.cc index 364bd7d3766..62aa5205f3c 100644 --- a/storage/tokudb/PerconaFT/portability/tests/test-pthread-rwlock-rdlock.cc +++ b/storage/tokudb/PerconaFT/portability/tests/test-pthread-rwlock-rdlock.cc @@ -48,7 +48,7 @@ int test_main(int argc __attribute__((__unused__)), char *const argv[] __attribu toku_pthread_rwlock_t rwlock; ZERO_STRUCT(rwlock); - toku_pthread_rwlock_init(&rwlock, NULL); + toku_pthread_rwlock_init(toku_uninstrumented, &rwlock, nullptr); toku_pthread_rwlock_rdlock(&rwlock); toku_pthread_rwlock_rdlock(&rwlock); toku_pthread_rwlock_rdunlock(&rwlock); diff --git a/storage/tokudb/PerconaFT/portability/tests/test-pthread-rwlock-rwr.cc b/storage/tokudb/PerconaFT/portability/tests/test-pthread-rwlock-rwr.cc index 3ca9e06bff7..92b30421ba9 100644 --- a/storage/tokudb/PerconaFT/portability/tests/test-pthread-rwlock-rwr.cc +++ b/storage/tokudb/PerconaFT/portability/tests/test-pthread-rwlock-rwr.cc @@ -71,13 +71,19 @@ int test_main(int argc , char *const argv[] ) { toku_pthread_t tid; void *retptr; - toku_pthread_rwlock_init(&rwlock, NULL); - state = 37; if (verbose) printf("%s:%d\n", __FUNCTION__, __LINE__); + toku_pthread_rwlock_init(toku_uninstrumented, &rwlock, nullptr); + state = 37; + if (verbose) + printf("%s:%d\n", __FUNCTION__, __LINE__); toku_pthread_rwlock_rdlock(&rwlock); - r = toku_pthread_create(&tid, NULL, f, &rwlock); assert(r == 0); + r = toku_pthread_create(toku_uninstrumented, &tid, nullptr, f, &rwlock); + assert(r == 0); - assert(state==37); state = 42; if (verbose) printf("%s:%d\n", __FUNCTION__, __LINE__); + assert(state == 37); + state = 42; + if (verbose) + printf("%s:%d\n", __FUNCTION__, __LINE__); sleep(4); assert(state==16); state = 44; if (verbose) printf("%s:%d\n", __FUNCTION__, __LINE__); toku_pthread_rwlock_rdlock(&rwlock); diff --git a/storage/tokudb/PerconaFT/portability/tests/test-stat.cc b/storage/tokudb/PerconaFT/portability/tests/test-stat.cc index 494a17bd074..57201764afb 100644 --- a/storage/tokudb/PerconaFT/portability/tests/test-stat.cc +++ b/storage/tokudb/PerconaFT/portability/tests/test-stat.cc @@ -47,10 +47,11 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. static void test_stat(const char *dirname, int result, int ex_errno) { int r; toku_struct_stat buf; - r = toku_stat(dirname, &buf); - //printf("stat %s %d %d\n", dirname, r, errno); fflush(stdout); - assert(r==result); - if (r!=0) assert(get_maybe_error_errno() == ex_errno); + r = toku_stat(dirname, &buf, toku_uninstrumented); + // printf("stat %s %d %d\n", dirname, r, errno); fflush(stdout); + assert(r == result); + if (r != 0) + assert(get_maybe_error_errno() == ex_errno); } int main(void) { diff --git a/storage/tokudb/PerconaFT/portability/tests/test-toku-malloc.cc b/storage/tokudb/PerconaFT/portability/tests/test-toku-malloc.cc index 1e1c7533c15..0d99b36b51a 100644 --- a/storage/tokudb/PerconaFT/portability/tests/test-toku-malloc.cc +++ b/storage/tokudb/PerconaFT/portability/tests/test-toku-malloc.cc @@ -53,10 +53,12 @@ int main(void) { int i; const int max_threads = 2; toku_pthread_t tids[max_threads]; - for (i=0; i<max_threads; i++) { - r = toku_pthread_create(&tids[i], NULL, f, 0); assert(r == 0); + for (i = 0; i < max_threads; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, f, nullptr); + assert(r == 0); } - for (i=0; i<max_threads; i++) { + for (i = 0; i < max_threads; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/portability/toku_assert.h b/storage/tokudb/PerconaFT/portability/toku_assert.h index 26a71cede7d..b0a7be3287b 100644 --- a/storage/tokudb/PerconaFT/portability/toku_assert.h +++ b/storage/tokudb/PerconaFT/portability/toku_assert.h @@ -53,13 +53,9 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #error NDEBUG should not be set #endif -static inline int get_error_errno(void); +inline int get_error_errno(void); -static inline int -get_maybe_error_errno(void) -{ - return errno; -} +static inline int get_maybe_error_errno(void) { return errno; } static inline void set_errno(int new_errno) @@ -139,12 +135,10 @@ void db_env_do_backtrace(FILE *outf); #define paranoid_invariant(a) ((void) 0) #define paranoid_invariant_null(a) ((void) 0) #define paranoid_invariant_notnull(a) ((void) 0) -#define paranoid_invariant_zero(a) ((void) 0) +#define paranoid_invariant_zero(a) ((void)0) #endif -static inline int -get_error_errno(void) -{ +inline int get_error_errno(void) { invariant(errno); return errno; } diff --git a/storage/tokudb/PerconaFT/portability/toku_instr_mysql.cc b/storage/tokudb/PerconaFT/portability/toku_instr_mysql.cc new file mode 100644 index 00000000000..b7b4c0ab233 --- /dev/null +++ b/storage/tokudb/PerconaFT/portability/toku_instr_mysql.cc @@ -0,0 +1,365 @@ +#ifdef MYSQL_TOKUDB_ENGINE +#include "toku_portability.h" +#include "toku_pthread.h" + +toku_instr_probe_pfs::toku_instr_probe_pfs(const toku_instr_key &key) + : mutex(new toku_mutex_t) { + toku_mutex_init(key, mutex.get(), nullptr); +} + +toku_instr_probe_pfs::~toku_instr_probe_pfs() { + toku_mutex_destroy(mutex.get()); +} + +// Thread instrumentation + +int toku_pthread_create(const toku_instr_key &key, + pthread_t *thread, + const pthread_attr_t *attr, + void *(*start_routine)(void *), + void *arg) { +#if (MYSQL_VERSION_MAJOR >= 5) && (MYSQL_VERSION_MINOR >= 7) + return PSI_THREAD_CALL(spawn_thread)( + key.id(), reinterpret_cast<my_thread_handle *>(thread), + attr, start_routine, arg); +#else + return PSI_THREAD_CALL(spawn_thread)( + key.id(), thread, attr, start_routine, arg); +#endif +} + +void toku_instr_register_current_thread(const toku_instr_key &key) { + struct PSI_thread *psi_thread = + PSI_THREAD_CALL(new_thread)(key.id(), nullptr, 0); + PSI_THREAD_CALL(set_thread)(psi_thread); +} + +void toku_instr_delete_current_thread() { + PSI_THREAD_CALL(delete_current_thread)(); +} + +// I/O instrumentation + +void toku_instr_file_open_begin(toku_io_instrumentation &io_instr, + const toku_instr_key &key, + toku_instr_file_op op, + const char *name, + const char *src_file, + int src_line) { + io_instr.locker = + PSI_FILE_CALL(get_thread_file_name_locker)( + &io_instr.state, key.id(), static_cast<PSI_file_operation>(op), + name, io_instr.locker); + if (io_instr.locker != nullptr) { + PSI_FILE_CALL(start_file_open_wait) + (io_instr.locker, src_file, src_line); + } +} + +void toku_instr_file_stream_open_end(toku_io_instrumentation &io_instr, + TOKU_FILE &file) { + file.key = nullptr; + if (FT_LIKELY(io_instr.locker)) { + file.key = + PSI_FILE_CALL(end_file_open_wait)(io_instr.locker, file.file); + } +} + +void toku_instr_file_open_end(toku_io_instrumentation &io_instr, int fd) { + if (FT_LIKELY(io_instr.locker)) + PSI_FILE_CALL(end_file_open_wait_and_bind_to_descriptor) + (io_instr.locker, fd); +} + +void toku_instr_file_name_close_begin(toku_io_instrumentation &io_instr, + const toku_instr_key &key, + toku_instr_file_op op, + const char *name, + const char *src_file, + int src_line) { + io_instr.locker = + PSI_FILE_CALL(get_thread_file_name_locker)( + &io_instr.state, key.id(), static_cast<PSI_file_operation>(op), + name, + io_instr.locker); + if (FT_LIKELY(io_instr.locker)) { + PSI_FILE_CALL(start_file_close_wait) + (io_instr.locker, src_file, src_line); + } +} + +void toku_instr_file_stream_close_begin(toku_io_instrumentation &io_instr, + toku_instr_file_op op, + const TOKU_FILE &file, + const char *src_file, + int src_line) { + io_instr.locker = nullptr; + if (FT_LIKELY(file.key)) { + io_instr.locker = PSI_FILE_CALL(get_thread_file_stream_locker)( + &io_instr.state, file.key, (PSI_file_operation)op); + if (FT_LIKELY(io_instr.locker)) { + PSI_FILE_CALL(start_file_close_wait) + (io_instr.locker, src_file, src_line); + } + } +} + +void toku_instr_file_fd_close_begin(toku_io_instrumentation &io_instr, + toku_instr_file_op op, + int fd, + const char *src_file, + int src_line) { + io_instr.locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( + &io_instr.state, fd, (PSI_file_operation)op); + if (FT_LIKELY(io_instr.locker)) { + PSI_FILE_CALL(start_file_close_wait) + (io_instr.locker, src_file, src_line); + } +} + +void toku_instr_file_close_end(const toku_io_instrumentation &io_instr, + int result) { + if (FT_LIKELY(io_instr.locker)) + PSI_FILE_CALL(end_file_close_wait) + (io_instr.locker, result); +} + +void toku_instr_file_io_begin(toku_io_instrumentation &io_instr, + toku_instr_file_op op, + int fd, + ssize_t count, + const char *src_file, + int src_line) { + io_instr.locker = PSI_FILE_CALL(get_thread_file_descriptor_locker)( + &io_instr.state, fd, (PSI_file_operation)op); + if (FT_LIKELY(io_instr.locker)) { + PSI_FILE_CALL(start_file_wait) + (io_instr.locker, count, src_file, src_line); + } +} + +void toku_instr_file_name_io_begin(toku_io_instrumentation &io_instr, + const toku_instr_key &key, + toku_instr_file_op op, + const char *name, + ssize_t count, + const char *src_file, + int src_line) { + io_instr.locker = + PSI_FILE_CALL(get_thread_file_name_locker)(&io_instr.state, + key.id(), + (PSI_file_operation)op, + name, + &io_instr.locker); + if (FT_LIKELY(io_instr.locker)) { + PSI_FILE_CALL(start_file_wait) + (io_instr.locker, count, src_file, src_line); + } +} + +void toku_instr_file_stream_io_begin(toku_io_instrumentation &io_instr, + toku_instr_file_op op, + const TOKU_FILE &file, + ssize_t count, + const char *src_file, + int src_line) { + io_instr.locker = nullptr; + if (FT_LIKELY(file.key)) { + io_instr.locker = PSI_FILE_CALL(get_thread_file_stream_locker)( + &io_instr.state, file.key, (PSI_file_operation)op); + if (FT_LIKELY(io_instr.locker)) { + PSI_FILE_CALL(start_file_wait) + (io_instr.locker, count, src_file, src_line); + } + } +} + +void toku_instr_file_io_end(toku_io_instrumentation &io_instr, ssize_t count) { + if (FT_LIKELY(io_instr.locker)) + PSI_FILE_CALL(end_file_wait) + (io_instr.locker, count); +} + +// Mutex instrumentation + +void toku_instr_mutex_init(const toku_instr_key &key, toku_mutex_t &mutex) { + mutex.psi_mutex = PSI_MUTEX_CALL(init_mutex)(key.id(), &mutex.pmutex); +#if TOKU_PTHREAD_DEBUG + mutex.instr_key_id = key.id(); +#endif +} + +void toku_instr_mutex_destroy(PSI_mutex *&mutex_instr) { + if (mutex_instr != nullptr) { + PSI_MUTEX_CALL(destroy_mutex)(mutex_instr); + mutex_instr = nullptr; + } +} + +void toku_instr_mutex_lock_start(toku_mutex_instrumentation &mutex_instr, + toku_mutex_t &mutex, + const char *src_file, + int src_line) { + mutex_instr.locker = nullptr; + if (mutex.psi_mutex) { + mutex_instr.locker = + PSI_MUTEX_CALL(start_mutex_wait)(&mutex_instr.state, + mutex.psi_mutex, + PSI_MUTEX_LOCK, + src_file, + src_line); + } +} + +void toku_instr_mutex_trylock_start(toku_mutex_instrumentation &mutex_instr, + toku_mutex_t &mutex, + const char *src_file, + int src_line) { + mutex_instr.locker = nullptr; + if (mutex.psi_mutex) { + mutex_instr.locker = + PSI_MUTEX_CALL(start_mutex_wait)(&mutex_instr.state, + mutex.psi_mutex, + PSI_MUTEX_TRYLOCK, + src_file, + src_line); + } +} + +void toku_instr_mutex_lock_end(toku_mutex_instrumentation &mutex_instr, + int pthread_mutex_lock_result) { + if (mutex_instr.locker) + PSI_MUTEX_CALL(end_mutex_wait) + (mutex_instr.locker, pthread_mutex_lock_result); +} + +void toku_instr_mutex_unlock(PSI_mutex *mutex_instr) { + if (mutex_instr) + PSI_MUTEX_CALL(unlock_mutex)(mutex_instr); +} + +// Condvar instrumentation + +void toku_instr_cond_init(const toku_instr_key &key, toku_cond_t &cond) { + cond.psi_cond = PSI_COND_CALL(init_cond)(key.id(), &cond.pcond); +#if TOKU_PTHREAD_DEBUG + cond.instr_key_id = key.id(); +#endif +} + +void toku_instr_cond_destroy(PSI_cond *&cond_instr) { + if (cond_instr != nullptr) { + PSI_COND_CALL(destroy_cond)(cond_instr); + cond_instr = nullptr; + } +} + +void toku_instr_cond_wait_start(toku_cond_instrumentation &cond_instr, + toku_instr_cond_op op, + toku_cond_t &cond, + toku_mutex_t &mutex, + const char *src_file, + int src_line) { + cond_instr.locker = nullptr; + if (cond.psi_cond) { + /* Instrumentation start */ + cond_instr.locker = + PSI_COND_CALL(start_cond_wait)(&cond_instr.state, + cond.psi_cond, + mutex.psi_mutex, + (PSI_cond_operation)op, + src_file, + src_line); + } +} + +void toku_instr_cond_wait_end(toku_cond_instrumentation &cond_instr, + int pthread_cond_wait_result) { + if (cond_instr.locker) + PSI_COND_CALL(end_cond_wait) + (cond_instr.locker, pthread_cond_wait_result); +} + +void toku_instr_cond_signal(const toku_cond_t &cond) { + if (cond.psi_cond) + PSI_COND_CALL(signal_cond)(cond.psi_cond); +} + +void toku_instr_cond_broadcast(const toku_cond_t &cond) { + if (cond.psi_cond) + PSI_COND_CALL(broadcast_cond)(cond.psi_cond); +} + +// rwlock instrumentation + +void toku_instr_rwlock_init(const toku_instr_key &key, + toku_pthread_rwlock_t &rwlock) { + rwlock.psi_rwlock = PSI_RWLOCK_CALL(init_rwlock)(key.id(), &rwlock.rwlock); +#if TOKU_PTHREAD_DEBUG + rwlock.instr_key_id = key.id(); +#endif +} + +void toku_instr_rwlock_destroy(PSI_rwlock *&rwlock_instr) { + if (rwlock_instr != nullptr) { + PSI_RWLOCK_CALL(destroy_rwlock)(rwlock_instr); + rwlock_instr = nullptr; + } +} + +void toku_instr_rwlock_rdlock_wait_start( + toku_rwlock_instrumentation &rwlock_instr, + toku_pthread_rwlock_t &rwlock, + const char *src_file, + int src_line) { + rwlock_instr.locker = nullptr; + if (rwlock.psi_rwlock) { + /* Instrumentation start */ + rwlock_instr.locker = + PSI_RWLOCK_CALL(start_rwlock_rdwait)(&rwlock_instr.state, + rwlock.psi_rwlock, + PSI_RWLOCK_READLOCK, + src_file, + src_line); + } +} + +void toku_instr_rwlock_wrlock_wait_start( + toku_rwlock_instrumentation &rwlock_instr, + toku_pthread_rwlock_t &rwlock, + const char *src_file, + int src_line) { + rwlock_instr.locker = nullptr; + if (rwlock.psi_rwlock) { + /* Instrumentation start */ + rwlock_instr.locker = + PSI_RWLOCK_CALL(start_rwlock_wrwait)(&rwlock_instr.state, + rwlock.psi_rwlock, + PSI_RWLOCK_WRITELOCK, + src_file, + src_line); + } +} + +void toku_instr_rwlock_rdlock_wait_end( + toku_rwlock_instrumentation &rwlock_instr, + int pthread_rwlock_wait_result) { + if (rwlock_instr.locker) + PSI_RWLOCK_CALL(end_rwlock_rdwait) + (rwlock_instr.locker, pthread_rwlock_wait_result); +} + +void toku_instr_rwlock_wrlock_wait_end( + toku_rwlock_instrumentation &rwlock_instr, + int pthread_rwlock_wait_result) { + if (rwlock_instr.locker) + PSI_RWLOCK_CALL(end_rwlock_wrwait) + (rwlock_instr.locker, pthread_rwlock_wait_result); +} + +void toku_instr_rwlock_unlock(toku_pthread_rwlock_t &rwlock) { + if (rwlock.psi_rwlock) + PSI_RWLOCK_CALL(unlock_rwlock)(rwlock.psi_rwlock); +} + +#endif // MYSQL_TOKUDB_ENGINE diff --git a/storage/tokudb/PerconaFT/portability/toku_instr_mysql.h b/storage/tokudb/PerconaFT/portability/toku_instr_mysql.h new file mode 100644 index 00000000000..d6b0ed35ce9 --- /dev/null +++ b/storage/tokudb/PerconaFT/portability/toku_instr_mysql.h @@ -0,0 +1,249 @@ +#ifdef TOKU_INSTR_MYSQL_H +// This file can be included only from toku_instumentation.h because +// it replaces the defintitions for the case if MySQL PFS is available +#error "toku_instr_mysql.h can be included only once" +#else // TOKU_INSTR_MYSQL_H +#define TOKU_INSTR_MYSQL_H + +#include <memory> + +// As these macros are defined in my_global.h +// and they are also defined in command line +// undefine them here to avoid compilation errors. +#undef __STDC_FORMAT_MACROS +#undef __STDC_LIMIT_MACROS +#include <mysql/psi/mysql_file.h> // PSI_file +#include <mysql/psi/mysql_thread.h> // PSI_mutex + +#ifndef HAVE_PSI_MUTEX_INTERFACE +#error HAVE_PSI_MUTEX_INTERFACE required +#endif +#ifndef HAVE_PSI_RWLOCK_INTERFACE +#error HAVE_PSI_RWLOCK_INTERFACE required +#endif +#ifndef HAVE_PSI_THREAD_INTERFACE +#error HAVE_PSI_THREAD_INTERFACE required +#endif + +// Instrumentation keys + +class toku_instr_key { + private: + pfs_key_t m_id; + + public: + toku_instr_key(toku_instr_object_type type, + const char *group, + const char *name) { + switch (type) { + case toku_instr_object_type::mutex: { + PSI_mutex_info mutex_info{&m_id, name, 0}; + mysql_mutex_register(group, &mutex_info, 1); + } break; + case toku_instr_object_type::rwlock: { + PSI_rwlock_info rwlock_info{&m_id, name, 0}; + mysql_rwlock_register(group, &rwlock_info, 1); + } break; + case toku_instr_object_type::cond: { + PSI_cond_info cond_info{&m_id, name, 0}; + mysql_cond_register(group, &cond_info, 1); + } break; + case toku_instr_object_type::thread: { + PSI_thread_info thread_info{&m_id, name, 0}; + mysql_thread_register(group, &thread_info, 1); + } break; + case toku_instr_object_type::file: { + PSI_file_info file_info{&m_id, name, 0}; + mysql_file_register(group, &file_info, 1); + } break; + } + } + + explicit toku_instr_key(pfs_key_t key_id) : m_id(key_id) {} + + pfs_key_t id() const { return m_id; } +}; + +// Thread instrumentation +int toku_pthread_create(const toku_instr_key &key, + pthread_t *thread, + const pthread_attr_t *attr, + void *(*start_routine)(void *), + void *arg); +void toku_instr_register_current_thread(const toku_instr_key &key); +void toku_instr_delete_current_thread(); + +// I/O instrumentation + +enum class toku_instr_file_op { + file_stream_open = PSI_FILE_STREAM_OPEN, + file_create = PSI_FILE_CREATE, + file_open = PSI_FILE_OPEN, + file_delete = PSI_FILE_DELETE, + file_rename = PSI_FILE_RENAME, + file_read = PSI_FILE_READ, + file_write = PSI_FILE_WRITE, + file_sync = PSI_FILE_SYNC, + file_stream_close = PSI_FILE_STREAM_CLOSE, + file_close = PSI_FILE_CLOSE, + file_stat = PSI_FILE_STAT +}; + +struct toku_io_instrumentation { + struct PSI_file_locker *locker; + PSI_file_locker_state state; + + toku_io_instrumentation() : locker(nullptr) {} +}; + +void toku_instr_file_open_begin(toku_io_instrumentation &io_instr, + const toku_instr_key &key, + toku_instr_file_op op, + const char *name, + const char *src_file, + int src_line); +void toku_instr_file_stream_open_end(toku_io_instrumentation &io_instr, + TOKU_FILE &file); +void toku_instr_file_open_end(toku_io_instrumentation &io_instr, int fd); +void toku_instr_file_name_close_begin(toku_io_instrumentation &io_instr, + const toku_instr_key &key, + toku_instr_file_op op, + const char *name, + const char *src_file, + int src_line); +void toku_instr_file_stream_close_begin(toku_io_instrumentation &io_instr, + toku_instr_file_op op, + const TOKU_FILE &file, + const char *src_file, + int src_line); +void toku_instr_file_fd_close_begin(toku_io_instrumentation &io_instr, + toku_instr_file_op op, + int fd, + const char *src_file, + int src_line); +void toku_instr_file_close_end(const toku_io_instrumentation &io_instr, + int result); +void toku_instr_file_io_begin(toku_io_instrumentation &io_instr, + toku_instr_file_op op, + int fd, + ssize_t count, + const char *src_file, + int src_line); +void toku_instr_file_name_io_begin(toku_io_instrumentation &io_instr, + const toku_instr_key &key, + toku_instr_file_op op, + const char *name, + ssize_t count, + const char *src_file, + int src_line); +void toku_instr_file_stream_io_begin(toku_io_instrumentation &io_instr, + toku_instr_file_op op, + const TOKU_FILE &file, + ssize_t count, + const char *src_file, + int src_line); +void toku_instr_file_io_end(toku_io_instrumentation &io_instr, ssize_t count); + +// Mutex instrumentation + +struct toku_mutex_instrumentation { + struct PSI_mutex_locker *locker; + PSI_mutex_locker_state state; + + toku_mutex_instrumentation() : locker(nullptr) {} +}; + +void toku_instr_mutex_init(const toku_instr_key &key, toku_mutex_t &mutex); +void toku_instr_mutex_destroy(PSI_mutex *&mutex_instr); +void toku_instr_mutex_lock_start(toku_mutex_instrumentation &mutex_instr, + toku_mutex_t &mutex, + const char *src_file, + int src_line); +void toku_instr_mutex_trylock_start(toku_mutex_instrumentation &mutex_instr, + toku_mutex_t &mutex, + const char *src_file, + int src_line); +void toku_instr_mutex_lock_end(toku_mutex_instrumentation &mutex_instr, + int pthread_mutex_lock_result); +void toku_instr_mutex_unlock(PSI_mutex *mutex_instr); + +// Instrumentation probes + +class toku_instr_probe_pfs { + private: + std::unique_ptr<toku_mutex_t> mutex; + toku_mutex_instrumentation mutex_instr; + + public: + explicit toku_instr_probe_pfs(const toku_instr_key &key); + + ~toku_instr_probe_pfs(); + + void start_with_source_location(const char *src_file, int src_line) { + mutex_instr.locker = nullptr; + toku_instr_mutex_lock_start(mutex_instr, *mutex, src_file, src_line); + } + + void stop() { toku_instr_mutex_lock_end(mutex_instr, 0); } +}; + +typedef toku_instr_probe_pfs toku_instr_probe; + +// Condvar instrumentation + +struct toku_cond_instrumentation { + struct PSI_cond_locker *locker; + PSI_cond_locker_state state; + + toku_cond_instrumentation() : locker(nullptr) {} +}; + +enum class toku_instr_cond_op { + cond_wait = PSI_COND_WAIT, + cond_timedwait = PSI_COND_TIMEDWAIT, +}; + +void toku_instr_cond_init(const toku_instr_key &key, toku_cond_t &cond); +void toku_instr_cond_destroy(PSI_cond *&cond_instr); +void toku_instr_cond_wait_start(toku_cond_instrumentation &cond_instr, + toku_instr_cond_op op, + toku_cond_t &cond, + toku_mutex_t &mutex, + const char *src_file, + int src_line); +void toku_instr_cond_wait_end(toku_cond_instrumentation &cond_instr, + int pthread_cond_wait_result); +void toku_instr_cond_signal(const toku_cond_t &cond); +void toku_instr_cond_broadcast(const toku_cond_t &cond); + +// rwlock instrumentation + +struct toku_rwlock_instrumentation { + struct PSI_rwlock_locker *locker; + PSI_rwlock_locker_state state; + + toku_rwlock_instrumentation() : locker(nullptr) { } +}; + +void toku_instr_rwlock_init(const toku_instr_key &key, + toku_pthread_rwlock_t &rwlock); +void toku_instr_rwlock_destroy(PSI_rwlock *&rwlock_instr); +void toku_instr_rwlock_rdlock_wait_start( + toku_rwlock_instrumentation &rwlock_instr, + toku_pthread_rwlock_t &rwlock, + const char *src_file, + int src_line); +void toku_instr_rwlock_wrlock_wait_start( + toku_rwlock_instrumentation &rwlock_instr, + toku_pthread_rwlock_t &rwlock, + const char *src_file, + int src_line); +void toku_instr_rwlock_rdlock_wait_end( + toku_rwlock_instrumentation &rwlock_instr, + int pthread_rwlock_wait_result); +void toku_instr_rwlock_wrlock_wait_end( + toku_rwlock_instrumentation &rwlock_instr, + int pthread_rwlock_wait_result); +void toku_instr_rwlock_unlock(toku_pthread_rwlock_t &rwlock); + +#endif // TOKU_INSTR_MYSQL_H diff --git a/storage/tokudb/PerconaFT/portability/toku_instrumentation.h b/storage/tokudb/PerconaFT/portability/toku_instrumentation.h new file mode 100644 index 00000000000..8c9390edc0a --- /dev/null +++ b/storage/tokudb/PerconaFT/portability/toku_instrumentation.h @@ -0,0 +1,339 @@ +#pragma once + +#include <stdio.h> // FILE + +// Performance instrumentation object identifier type +typedef unsigned int pfs_key_t; + +enum class toku_instr_object_type { mutex, rwlock, cond, thread, file }; + +struct PSI_file; + +struct TOKU_FILE { + /** The real file. */ + FILE *file; + struct PSI_file *key; + TOKU_FILE() : file(nullptr), key(nullptr) {} +}; + +struct PSI_mutex; +struct PSI_cond; +struct PSI_rwlock; + +struct toku_mutex_t; +struct toku_cond_t; +struct toku_pthread_rwlock_t; + +class toku_instr_key; + +class toku_instr_probe_empty { + public: + explicit toku_instr_probe_empty(UU(const toku_instr_key &key)) {} + + void start_with_source_location(UU(const char *src_file), + UU(int src_line)) {} + + void stop() {} +}; + +#define TOKU_PROBE_START(p) p->start_with_source_location(__FILE__, __LINE__) +#define TOKU_PROBE_STOP(p) p->stop + +extern toku_instr_key toku_uninstrumented; + +#ifndef MYSQL_TOKUDB_ENGINE + +#include <pthread.h> + +class toku_instr_key { + public: + toku_instr_key(UU(toku_instr_object_type type), + UU(const char *group), + UU(const char *name)) {} + + explicit toku_instr_key(UU(pfs_key_t key_id)) {} +}; + +typedef toku_instr_probe_empty toku_instr_probe; + +enum class toku_instr_file_op { + file_stream_open, + file_create, + file_open, + file_delete, + file_rename, + file_read, + file_write, + file_sync, + file_stream_close, + file_close, + file_stat +}; + +struct PSI_file {}; +struct PSI_mutex {}; + +struct toku_io_instrumentation {}; + +inline int toku_pthread_create(UU(const toku_instr_key &key), + pthread_t *thread, + const pthread_attr_t *attr, + void *(*start_routine)(void *), + void *arg) { + return pthread_create(thread, attr, start_routine, arg); +} + +inline void toku_instr_register_current_thread() {} + +inline void toku_instr_delete_current_thread() {} + +// Instrument file creation, opening, closing, and renaming +inline void toku_instr_file_open_begin(UU(toku_io_instrumentation &io_instr), + UU(const toku_instr_key &key), + UU(toku_instr_file_op op), + UU(const char *name), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_file_stream_open_end( + UU(toku_io_instrumentation &io_instr), + UU(TOKU_FILE &file)) {} + +inline void toku_instr_file_open_end(UU(toku_io_instrumentation &io_instr), + UU(int fd)) {} + +inline void toku_instr_file_name_close_begin( + UU(toku_io_instrumentation &io_instr), + UU(const toku_instr_key &key), + UU(toku_instr_file_op op), + UU(const char *name), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_file_stream_close_begin( + UU(toku_io_instrumentation &io_instr), + UU(toku_instr_file_op op), + UU(TOKU_FILE &file), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_file_fd_close_begin( + UU(toku_io_instrumentation &io_instr), + UU(toku_instr_file_op op), + UU(int fd), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_file_close_end(UU(toku_io_instrumentation &io_instr), + UU(int result)) {} + +inline void toku_instr_file_io_begin(UU(toku_io_instrumentation &io_instr), + UU(toku_instr_file_op op), + UU(int fd), + UU(unsigned int count), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_file_name_io_begin(UU(toku_io_instrumentation &io_instr), + UU(const toku_instr_key &key), + UU(toku_instr_file_op op), + UU(const char *name), + UU(unsigned int count), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_file_stream_io_begin( + UU(toku_io_instrumentation &io_instr), + UU(toku_instr_file_op op), + UU(TOKU_FILE &file), + UU(unsigned int count), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_file_io_end(UU(toku_io_instrumentation &io_instr), + UU(unsigned int count)) {} + +struct toku_mutex_t; + +struct toku_mutex_instrumentation {}; + +inline PSI_mutex *toku_instr_mutex_init(UU(const toku_instr_key &key), + UU(toku_mutex_t &mutex)) { + return nullptr; +} + +inline void toku_instr_mutex_destroy(UU(PSI_mutex *&mutex_instr)) {} + +inline void toku_instr_mutex_lock_start( + UU(toku_mutex_instrumentation &mutex_instr), + UU(toku_mutex_t &mutex), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_mutex_trylock_start( + UU(toku_mutex_instrumentation &mutex_instr), + UU(toku_mutex_t &mutex), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_mutex_lock_end( + UU(toku_mutex_instrumentation &mutex_instr), + UU(int pthread_mutex_lock_result)) {} + +inline void toku_instr_mutex_unlock(UU(PSI_mutex *mutex_instr)) {} + +struct toku_cond_instrumentation {}; + +enum class toku_instr_cond_op { + cond_wait, + cond_timedwait, +}; + +inline PSI_cond *toku_instr_cond_init(UU(const toku_instr_key &key), + UU(toku_cond_t &cond)) { + return nullptr; +} + +inline void toku_instr_cond_destroy(UU(PSI_cond *&cond_instr)) {} + +inline void toku_instr_cond_wait_start( + UU(toku_cond_instrumentation &cond_instr), + UU(toku_instr_cond_op op), + UU(toku_cond_t &cond), + UU(toku_mutex_t &mutex), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_cond_wait_end(UU(toku_cond_instrumentation &cond_instr), + UU(int pthread_cond_wait_result)) {} + +inline void toku_instr_cond_signal(UU(toku_cond_t &cond)) {} + +inline void toku_instr_cond_broadcast(UU(toku_cond_t &cond)) {} + +// rwlock instrumentation +struct toku_rwlock_instrumentation {}; + +inline PSI_rwlock *toku_instr_rwlock_init(UU(const toku_instr_key &key), + UU(toku_pthread_rwlock_t &rwlock)) { + return nullptr; +} + +inline void toku_instr_rwlock_destroy(UU(PSI_rwlock *&rwlock_instr)) {} + +inline void toku_instr_rwlock_rdlock_wait_start( + UU(toku_rwlock_instrumentation &rwlock_instr), + UU(toku_pthread_rwlock_t &rwlock), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_rwlock_wrlock_wait_start( + UU(toku_rwlock_instrumentation &rwlock_instr), + UU(toku_pthread_rwlock_t &rwlock), + UU(const char *src_file), + UU(int src_line)) {} + +inline void toku_instr_rwlock_rdlock_wait_end( + UU(toku_rwlock_instrumentation &rwlock_instr), + UU(int pthread_rwlock_wait_result)) {} + +inline void toku_instr_rwlock_wrlock_wait_end( + UU(toku_rwlock_instrumentation &rwlock_instr), + UU(int pthread_rwlock_wait_result)) {} + +inline void toku_instr_rwlock_unlock(UU(toku_pthread_rwlock_t &rwlock)) {} + +#else // MYSQL_TOKUDB_ENGINE +// There can be not only mysql but also mongodb or any other PFS stuff +#include <toku_instr_mysql.h> +#endif // MYSQL_TOKUDB_ENGINE + +extern toku_instr_key toku_uninstrumented; + +extern toku_instr_probe *toku_instr_probe_1; + +// threads +extern toku_instr_key *extractor_thread_key; +extern toku_instr_key *fractal_thread_key; +extern toku_instr_key *io_thread_key; +extern toku_instr_key *eviction_thread_key; +extern toku_instr_key *kibbutz_thread_key; +extern toku_instr_key *minicron_thread_key; +extern toku_instr_key *tp_internal_thread_key; + +// Files +extern toku_instr_key *tokudb_file_data_key; +extern toku_instr_key *tokudb_file_load_key; +extern toku_instr_key *tokudb_file_tmp_key; +extern toku_instr_key *tokudb_file_log_key; + +// Mutexes +extern toku_instr_key *kibbutz_mutex_key; +extern toku_instr_key *minicron_p_mutex_key; +extern toku_instr_key *queue_result_mutex_key; +extern toku_instr_key *tpool_lock_mutex_key; +extern toku_instr_key *workset_lock_mutex_key; +extern toku_instr_key *bjm_jobs_lock_mutex_key; +extern toku_instr_key *log_internal_lock_mutex_key; +extern toku_instr_key *cachetable_ev_thread_lock_mutex_key; +extern toku_instr_key *cachetable_disk_nb_mutex_key; +extern toku_instr_key *cachetable_m_mutex_key; +extern toku_instr_key *safe_file_size_lock_mutex_key; +extern toku_instr_key *checkpoint_safe_mutex_key; +extern toku_instr_key *ft_ref_lock_mutex_key; +extern toku_instr_key *loader_error_mutex_key; +extern toku_instr_key *bfs_mutex_key; +extern toku_instr_key *loader_bl_mutex_key; +extern toku_instr_key *loader_fi_lock_mutex_key; +extern toku_instr_key *loader_out_mutex_key; +extern toku_instr_key *result_output_condition_lock_mutex_key; +extern toku_instr_key *block_table_mutex_key; +extern toku_instr_key *rollback_log_node_cache_mutex_key; +extern toku_instr_key *txn_lock_mutex_key; +extern toku_instr_key *txn_state_lock_mutex_key; +extern toku_instr_key *txn_child_manager_mutex_key; +extern toku_instr_key *txn_manager_lock_mutex_key; +extern toku_instr_key *treenode_mutex_key; +extern toku_instr_key *manager_mutex_key; +extern toku_instr_key *manager_escalation_mutex_key; +extern toku_instr_key *manager_escalator_mutex_key; +extern toku_instr_key *db_txn_struct_i_txn_mutex_key; +extern toku_instr_key *indexer_i_indexer_lock_mutex_key; +extern toku_instr_key *indexer_i_indexer_estimate_lock_mutex_key; +extern toku_instr_key *locktree_request_info_mutex_key; +extern toku_instr_key *locktree_request_info_retry_mutex_key; + +// condition vars +extern toku_instr_key *result_state_cond_key; +extern toku_instr_key *bjm_jobs_wait_key; +extern toku_instr_key *cachetable_p_refcount_wait_key; +extern toku_instr_key *cachetable_m_flow_control_cond_key; +extern toku_instr_key *cachetable_m_ev_thread_cond_key; +extern toku_instr_key *bfs_cond_key; +extern toku_instr_key *result_output_condition_key; +extern toku_instr_key *manager_m_escalator_done_key; +extern toku_instr_key *lock_request_m_wait_cond_key; +extern toku_instr_key *queue_result_cond_key; +extern toku_instr_key *ws_worker_wait_key; +extern toku_instr_key *rwlock_wait_read_key; +extern toku_instr_key *rwlock_wait_write_key; +extern toku_instr_key *rwlock_cond_key; +extern toku_instr_key *tp_thread_wait_key; +extern toku_instr_key *tp_pool_wait_free_key; +extern toku_instr_key *frwlock_m_wait_read_key; +extern toku_instr_key *kibbutz_k_cond_key; +extern toku_instr_key *minicron_p_condvar_key; +extern toku_instr_key *locktree_request_info_retry_cv_key; + +// rwlocks +extern toku_instr_key *multi_operation_lock_key; +extern toku_instr_key *low_priority_multi_operation_lock_key; +extern toku_instr_key *cachetable_m_list_lock_key; +extern toku_instr_key *cachetable_m_pending_lock_expensive_key; +extern toku_instr_key *cachetable_m_pending_lock_cheap_key; +extern toku_instr_key *cachetable_m_lock_key; +extern toku_instr_key *result_i_open_dbs_rwlock_key; +extern toku_instr_key *checkpoint_safe_rwlock_key; +extern toku_instr_key *cachetable_value_key; +extern toku_instr_key *safe_file_size_lock_rwlock_key; +extern toku_instr_key *cachetable_disk_nb_rwlock_key; diff --git a/storage/tokudb/PerconaFT/portability/toku_os.h b/storage/tokudb/PerconaFT/portability/toku_os.h index 3a0e7376971..d7cfcfefb9a 100644 --- a/storage/tokudb/PerconaFT/portability/toku_os.h +++ b/storage/tokudb/PerconaFT/portability/toku_os.h @@ -116,12 +116,10 @@ int toku_fsync_dir_by_name_without_accounting(const char *dir_name); // *free_size is set to the bytes of free space in the file system // *total_size is set to the total bytes in the file system // Return 0 on success, otherwise an error number -int toku_get_filesystem_sizes(const char *path, uint64_t *avail_size, uint64_t *free_size, uint64_t *total_size); - -// Portable linux 'stat' -int toku_stat(const char *name, toku_struct_stat *statbuf) __attribute__((__visibility__("default"))); -// Portable linux 'fstat' -int toku_fstat(int fd, toku_struct_stat *statbuf) __attribute__((__visibility__("default"))); +int toku_get_filesystem_sizes(const char *path, + uint64_t *avail_size, + uint64_t *free_size, + uint64_t *total_size); // Portable linux 'dup2' int toku_dup2(int fd, int fd2) __attribute__((__visibility__("default"))); diff --git a/storage/tokudb/PerconaFT/portability/toku_portability.h b/storage/tokudb/PerconaFT/portability/toku_portability.h index d3a4e391a9f..b01a375a89d 100644 --- a/storage/tokudb/PerconaFT/portability/toku_portability.h +++ b/storage/tokudb/PerconaFT/portability/toku_portability.h @@ -125,6 +125,33 @@ typedef int64_t toku_off_t; #define UU(x) x __attribute__((__unused__)) +// Branch prediction macros. +// If supported by the compiler, will hint in inctruction caching for likely +// branching. Should only be used where there is a very good idea of the correct +// branch heuristics as determined by profiling. Mostly copied from InnoDB. +// Use: +// "if (FT_LIKELY(x))" where the chances of "x" evaluating true are higher +// "if (FT_UNLIKELY(x))" where the chances of "x" evaluating false are higher +#if defined(__GNUC__) && (__GNUC__ > 2) && !defined(__INTEL_COMPILER) + +// Tell the compiler that 'expr' probably evaluates to 'constant'. +#define FT_EXPECT(expr, constant) __builtin_expect(expr, constant) + +#else + +#warning "No FT branch prediction operations in use!" +#define FT_EXPECT(expr, constant) (expr) + +#endif // defined(__GNUC__) && (__GNUC__ > 2) && ! defined(__INTEL_COMPILER) + +// Tell the compiler that cond is likely to hold +#define FT_LIKELY(cond) FT_EXPECT(bool(cond), true) + +// Tell the compiler that cond is unlikely to hold +#define FT_UNLIKELY(cond) FT_EXPECT(bool(cond), false) + +#include "toku_instrumentation.h" + #if defined(__cplusplus) extern "C" { #endif @@ -242,28 +269,272 @@ void toku_os_full_write (int fd, const void *buf, size_t len) __attribute__((__v // os_write returns 0 on success, otherwise an errno. ssize_t toku_os_pwrite (int fd, const void *buf, size_t len, toku_off_t off) __attribute__((__visibility__("default"))); -int toku_os_write (int fd, const void *buf, size_t len) __attribute__((__visibility__("default"))); +int toku_os_write(int fd, const void *buf, size_t len) + __attribute__((__visibility__("default"))); // wrappers around file system calls -FILE * toku_os_fdopen(int fildes, const char *mode); -FILE * toku_os_fopen(const char *filename, const char *mode); -int toku_os_open(const char *path, int oflag, int mode); -int toku_os_open_direct(const char *path, int oflag, int mode); -int toku_os_close(int fd); -int toku_os_fclose(FILE * stream); -int toku_os_rename(const char *old_name, const char *new_name); -int toku_os_unlink(const char *path); -ssize_t toku_os_read(int fd, void *buf, size_t count); -ssize_t toku_os_pread(int fd, void *buf, size_t count, off_t offset); void toku_os_recursive_delete(const char *path); +TOKU_FILE *toku_os_fdopen_with_source_location(int fildes, + const char *mode, + const char *filename, + const toku_instr_key &instr_key, + const char *src_file, + uint src_line); +#define toku_os_fdopen(FD, M, FN, K) \ + toku_os_fdopen_with_source_location(FD, M, FN, K, __FILE__, __LINE__) + +TOKU_FILE *toku_os_fopen_with_source_location(const char *filename, + const char *mode, + const toku_instr_key &instr_key, + const char *src_file, + uint src_line); +#define toku_os_fopen(F, M, K) \ + toku_os_fopen_with_source_location(F, M, K, __FILE__, __LINE__) + +int toku_os_open_with_source_location(const char *path, + int oflag, + int mode, + const toku_instr_key &instr_key, + const char *src_file, + uint src_line); +#define toku_os_open(FD, F, M, K) \ + toku_os_open_with_source_location(FD, F, M, K, __FILE__, __LINE__) + +int toku_os_open_direct(const char *path, + int oflag, + int mode, + const toku_instr_key &instr_key); + +int toku_os_delete_with_source_location(const char *name, + const char *src_file, + uint src_line); +#define toku_os_delete(FN) \ + toku_os_delete_with_source_location(FN, __FILE__, __LINE__) + +int toku_os_rename_with_source_location(const char *old_name, + const char *new_name, + const char *src_file, + uint src_line); +#define toku_os_rename(old_name, new_name) \ + toku_os_rename_with_source_location(old_name, new_name, __FILE__, __LINE__) + +void toku_os_full_write_with_source_location(int fd, + const void *buf, + size_t len, + const char *src_file, + uint src_line); +#define toku_os_full_write(FD, B, L) \ + toku_os_full_write_with_source_location(FD, B, L, __FILE__, __LINE__) + +int toku_os_write_with_source_location(int fd, + const void *buf, + size_t len, + const char *src_file, + uint src_line); +#define toku_os_write(FD, B, L) \ + toku_os_write_with_source_location(FD, B, L, __FILE__, __LINE__) + +void toku_os_full_pwrite_with_source_location(int fd, + const void *buf, + size_t len, + toku_off_t off, + const char *src_file, + uint src_line); +#define toku_os_full_pwrite(FD, B, L, O) \ + toku_os_full_pwrite_with_source_location(FD, B, L, O, __FILE__, __LINE__) + +ssize_t toku_os_pwrite_with_source_location(int fd, + const void *buf, + size_t len, + toku_off_t off, + const char *src_file, + uint src_line); + +#define toku_os_pwrite(FD, B, L, O) \ + toku_os_pwrite_with_source_location(FD, B, L, O, __FILE__, __LINE__) + +int toku_os_fwrite_with_source_location(const void *ptr, + size_t size, + size_t nmemb, + TOKU_FILE *stream, + const char *src_file, + uint src_line); + +#define toku_os_fwrite(P, S, N, FS) \ + toku_os_fwrite_with_source_location(P, S, N, FS, __FILE__, __LINE__) + +int toku_os_fread_with_source_location(void *ptr, + size_t size, + size_t nmemb, + TOKU_FILE *stream, + const char *src_file, + uint src_line); +#define toku_os_fread(P, S, N, FS) \ + toku_os_fread_with_source_location(P, S, N, FS, __FILE__, __LINE__) + +TOKU_FILE *toku_os_fopen_with_source_location(const char *filename, + const char *mode, + const toku_instr_key &instr_key, + const char *src_file, + uint src_line); + +int toku_os_fclose_with_source_location(TOKU_FILE *stream, + const char *src_file, + uint src_line); + +#define toku_os_fclose(FS) \ + toku_os_fclose_with_source_location(FS, __FILE__, __LINE__) + +int toku_os_close_with_source_location(int fd, + const char *src_file, + uint src_line); +#define toku_os_close(FD) \ + toku_os_close_with_source_location(FD, __FILE__, __LINE__) + +ssize_t toku_os_read_with_source_location(int fd, + void *buf, + size_t count, + const char *src_file, + uint src_line); + +#define toku_os_read(FD, B, C) \ + toku_os_read_with_source_location(FD, B, C, __FILE__, __LINE__); + +ssize_t inline_toku_os_pread_with_source_location(int fd, + void *buf, + size_t count, + off_t offset, + const char *src_file, + uint src_line); +#define toku_os_pread(FD, B, C, O) \ + inline_toku_os_pread_with_source_location(FD, B, C, O, __FILE__, __LINE__); + +void file_fsync_internal_with_source_location(int fd, + const char *src_file, + uint src_line); + +#define file_fsync_internal(FD) \ + file_fsync_internal_with_source_location(FD, __FILE__, __LINE__); + +int toku_os_get_file_size_with_source_location(int fildes, + int64_t *fsize, + const char *src_file, + uint src_line); + +#define toku_os_get_file_size(D, S) \ + toku_os_get_file_size_with_source_location(D, S, __FILE__, __LINE__) + +// TODO: should this prototype be moved to toku_os.h? +int toku_stat_with_source_location(const char *name, + toku_struct_stat *buf, + const toku_instr_key &instr_key, + const char *src_file, + uint src_line) + __attribute__((__visibility__("default"))); + +#define toku_stat(N, B, K) \ + toku_stat_with_source_location(N, B, K, __FILE__, __LINE__) + +int toku_os_fstat_with_source_location(int fd, + toku_struct_stat *buf, + const char *src_file, + uint src_line) + __attribute__((__visibility__("default"))); + +#define toku_os_fstat(FD, B) \ + toku_os_fstat_with_source_location(FD, B, __FILE__, __LINE__) + +#ifdef HAVE_PSI_FILE_INTERFACE2 +int inline_toku_os_close(int fd, const char *src_file, uint src_line); +int inline_toku_os_fclose(TOKU_FILE *stream, + const char *src_file, + uint src_line); +ssize_t inline_toku_os_read(int fd, + void *buf, + size_t count, + const char *src_file, + uint src_line); +ssize_t inline_toku_os_pread(int fd, + void *buf, + size_t count, + off_t offset, + const char *src_file, + uint src_line); +int inline_toku_os_fwrite(const void *ptr, + size_t size, + size_t nmemb, + TOKU_FILE *stream, + const char *src_file, + uint src_line); +int inline_toku_os_fread(void *ptr, + size_t size, + size_t nmemb, + TOKU_FILE *stream, + const char *src_file, + uint src_line); +int inline_toku_os_write(int fd, + const void *buf, + size_t len, + const char *src_file, + uint src_line); +ssize_t inline_toku_os_pwrite(int fd, + const void *buf, + size_t len, + toku_off_t off, + const char *src_file, + uint src_line); +void inline_toku_os_full_write(int fd, + const void *buf, + size_t len, + const char *src_file, + uint src_line); +void inline_toku_os_full_pwrite(int fd, + const void *buf, + size_t len, + toku_off_t off, + const char *src_file, + uint src_line); +int inline_toku_os_delete(const char *name, + const char *srv_file, + uint src_line); +//#else +int inline_toku_os_close(int fd); +int inline_toku_os_fclose(TOKU_FILE *stream); +ssize_t inline_toku_os_read(int fd, void *buf, size_t count); +ssize_t inline_toku_os_pread(int fd, void *buf, size_t count, off_t offset); +int inline_toku_os_fwrite(const void *ptr, + size_t size, + size_t nmemb, + TOKU_FILE *stream); +int inline_toku_os_fread(void *ptr, + size_t size, + size_t nmemb, + TOKU_FILE *stream); +int inline_toku_os_write(int fd, const void *buf, size_t len); +ssize_t inline_toku_os_pwrite(int fd, + const void *buf, + size_t len, + toku_off_t off); +void inline_toku_os_full_write(int fd, const void *buf, size_t len); +void inline_toku_os_full_pwrite(int fd, + const void *buf, + size_t len, + toku_off_t off); +int inline_toku_os_delete(const char *name); +#endif + // wrapper around fsync -void toku_file_fsync_without_accounting(int fd); void toku_file_fsync(int fd); int toku_fsync_directory(const char *fname); +void toku_file_fsync_without_accounting(int fd); // get the number of fsync calls and the fsync times (total) -void toku_get_fsync_times(uint64_t *fsync_count, uint64_t *fsync_time, uint64_t *long_fsync_threshold, uint64_t *long_fsync_count, uint64_t *long_fsync_time); +void toku_get_fsync_times(uint64_t *fsync_count, + uint64_t *fsync_time, + uint64_t *long_fsync_threshold, + uint64_t *long_fsync_count, + uint64_t *long_fsync_time); void toku_set_func_fsync (int (*fsync_function)(int)); void toku_set_func_pwrite (ssize_t (*)(int, const void *, size_t, toku_off_t)); @@ -273,9 +544,11 @@ void toku_set_func_full_write (ssize_t (*)(int, const void *, size_t)); void toku_set_func_fdopen (FILE * (*)(int, const char *)); void toku_set_func_fopen (FILE * (*)(const char *, const char *)); void toku_set_func_open (int (*)(const char *, int, int)); -void toku_set_func_fclose(int (*)(FILE*)); +void toku_set_func_fclose(int (*)(FILE *)); void toku_set_func_read(ssize_t (*)(int, void *, size_t)); -void toku_set_func_pread (ssize_t (*)(int, void *, size_t, off_t)); +void toku_set_func_pread(ssize_t (*)(int, void *, size_t, off_t)); +void toku_set_func_fwrite( + size_t (*fwrite_fun)(const void *, size_t, size_t, FILE *)); int toku_portability_init(void); void toku_portability_destroy(void); @@ -285,28 +558,3 @@ void toku_portability_destroy(void); static inline uint64_t roundup_to_multiple(uint64_t alignment, uint64_t v) { return (v + alignment - 1) & ~(alignment - 1); } - -// Branch prediction macros. -// If supported by the compiler, will hint in inctruction caching for likely -// branching. Should only be used where there is a very good idea of the correct -// branch heuristics as determined by profiling. Mostly copied from InnoDB. -// Use: -// "if (FT_LIKELY(x))" where the chances of "x" evaluating true are higher -// "if (FT_UNLIKELY(x))" where the chances of "x" evaluating false are higher -#if defined(__GNUC__) && (__GNUC__ > 2) && ! defined(__INTEL_COMPILER) - -// Tell the compiler that 'expr' probably evaluates to 'constant'. -#define FT_EXPECT(expr,constant) __builtin_expect(expr, constant) - -#else - -#warning "No FT branch prediction operations in use!" -#define FT_EXPECT(expr,constant) (expr) - -#endif // defined(__GNUC__) && (__GNUC__ > 2) && ! defined(__INTEL_COMPILER) - -// Tell the compiler that cond is likely to hold -#define FT_LIKELY(cond) FT_EXPECT(cond, 1) - -// Tell the compiler that cond is unlikely to hold -#define FT_UNLIKELY(cond) FT_EXPECT(cond, 0) diff --git a/storage/tokudb/PerconaFT/portability/toku_pthread.h b/storage/tokudb/PerconaFT/portability/toku_pthread.h index 84c27736201..44de01244d2 100644 --- a/storage/tokudb/PerconaFT/portability/toku_pthread.h +++ b/storage/tokudb/PerconaFT/portability/toku_pthread.h @@ -42,31 +42,62 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include <time.h> #include <stdint.h> +#include "toku_portability.h" #include "toku_assert.h" +// TODO: some things moved toku_instrumentation.h, not necessarily the best +// place typedef pthread_attr_t toku_pthread_attr_t; typedef pthread_t toku_pthread_t; -typedef pthread_mutexattr_t toku_pthread_mutexattr_t; typedef pthread_mutex_t toku_pthread_mutex_t; typedef pthread_condattr_t toku_pthread_condattr_t; typedef pthread_cond_t toku_pthread_cond_t; -typedef pthread_rwlock_t toku_pthread_rwlock_t; -typedef pthread_rwlockattr_t toku_pthread_rwlockattr_t; +typedef pthread_rwlockattr_t toku_pthread_rwlockattr_t; typedef pthread_key_t toku_pthread_key_t; typedef struct timespec toku_timespec_t; -#ifndef TOKU_PTHREAD_DEBUG -# define TOKU_PTHREAD_DEBUG 0 -#endif +// TODO: break this include loop +#include <pthread.h> +typedef pthread_mutexattr_t toku_pthread_mutexattr_t; -typedef struct toku_mutex { +struct toku_mutex_t { pthread_mutex_t pmutex; + struct PSI_mutex + *psi_mutex; /* The performance schema instrumentation hook */ #if TOKU_PTHREAD_DEBUG - pthread_t owner; // = pthread_self(); // for debugging + pthread_t owner; // = pthread_self(); // for debugging bool locked; bool valid; + pfs_key_t instr_key_id; +#endif +}; + +struct toku_cond_t { + pthread_cond_t pcond; + struct PSI_cond *psi_cond; +#if TOKU_PTHREAD_DEBUG + pfs_key_t instr_key_id; +#endif +}; + +#ifdef TOKU_PTHREAD_DEBUG +#define TOKU_COND_INITIALIZER \ + { \ + .pcond = PTHREAD_COND_INITIALIZER, .psi_cond = nullptr, \ + .instr_key_id = 0 \ + } +#else +#define TOKU_COND_INITIALIZER \ + { .pcond = PTHREAD_COND_INITIALIZER, .psi_cond = nullptr } #endif -} toku_mutex_t; + +struct toku_pthread_rwlock_t { + pthread_rwlock_t rwlock; + struct PSI_rwlock *psi_rwlock; +#if TOKU_PTHREAD_DEBUG + pfs_key_t instr_key_id; +#endif +}; typedef struct toku_mutex_aligned { toku_mutex_t aligned_mutex __attribute__((__aligned__(64))); @@ -83,45 +114,68 @@ typedef struct toku_mutex_aligned { // In general it will be a lot of busy work to make this codebase compile // cleanly with -Wmissing-field-initializers -# define ZERO_MUTEX_INITIALIZER {} +#define ZERO_MUTEX_INITIALIZER \ + {} #if TOKU_PTHREAD_DEBUG -# define TOKU_MUTEX_INITIALIZER { .pmutex = PTHREAD_MUTEX_INITIALIZER, .owner = 0, .locked = false, .valid = true } +#define TOKU_MUTEX_INITIALIZER \ + { \ + .pmutex = PTHREAD_MUTEX_INITIALIZER, .psi_mutex = nullptr, .owner = 0, \ + .locked = false, .valid = true, .instr_key_id = 0 \ + } #else -# define TOKU_MUTEX_INITIALIZER { .pmutex = PTHREAD_MUTEX_INITIALIZER } +#define TOKU_MUTEX_INITIALIZER \ + { .pmutex = PTHREAD_MUTEX_INITIALIZER, .psi_mutex = nullptr } #endif // Darwin doesn't provide adaptive mutexes #if defined(__APPLE__) -# define TOKU_MUTEX_ADAPTIVE PTHREAD_MUTEX_DEFAULT -# if TOKU_PTHREAD_DEBUG -# define TOKU_ADAPTIVE_MUTEX_INITIALIZER { .pmutex = PTHREAD_MUTEX_INITIALIZER, .owner = 0, .locked = false, .valid = true } -# else -# define TOKU_ADAPTIVE_MUTEX_INITIALIZER { .pmutex = PTHREAD_MUTEX_INITIALIZER } -# endif -#else // __FreeBSD__, __linux__, at least -# define TOKU_MUTEX_ADAPTIVE PTHREAD_MUTEX_ADAPTIVE_NP -# if TOKU_PTHREAD_DEBUG -# define TOKU_ADAPTIVE_MUTEX_INITIALIZER { .pmutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP, .owner = 0, .locked = false, .valid = true } -# else -# define TOKU_ADAPTIVE_MUTEX_INITIALIZER { .pmutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP } -# endif +#define TOKU_MUTEX_ADAPTIVE PTHREAD_MUTEX_DEFAULT +#if TOKU_PTHREAD_DEBUG +#define TOKU_ADAPTIVE_MUTEX_INITIALIZER \ + { \ + .pmutex = PTHREAD_MUTEX_INITIALIZER, .psi_mutex = nullptr, .owner = 0, \ + .locked = false, .valid = true, .instr_key_id = 0 \ + } +#else +#define TOKU_ADAPTIVE_MUTEX_INITIALIZER \ + { .pmutex = PTHREAD_MUTEX_INITIALIZER, .psi_mutex = nullptr } #endif - -static inline void -toku_mutex_init(toku_mutex_t *mutex, const toku_pthread_mutexattr_t *attr) { - int r = pthread_mutex_init(&mutex->pmutex, attr); - assert_zero(r); +#else // __FreeBSD__, __linux__, at least +#define TOKU_MUTEX_ADAPTIVE PTHREAD_MUTEX_ADAPTIVE_NP #if TOKU_PTHREAD_DEBUG - mutex->locked = false; - invariant(!mutex->valid); - mutex->valid = true; - mutex->owner = 0; +#define TOKU_ADAPTIVE_MUTEX_INITIALIZER \ + { \ + .pmutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP, .psi_mutex = nullptr, \ + .owner = 0, .locked = false, .valid = true, .instr_key_id = 0 \ + } +#else +#define TOKU_ADAPTIVE_MUTEX_INITIALIZER \ + { .pmutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP, .psi_mutex = nullptr } +#endif #endif -} -static inline void -toku_mutexattr_init(toku_pthread_mutexattr_t *attr) { +// Different OSes implement mutexes as different amounts of nested structs. +// C++ will fill out all missing values with zeroes if you provide at least one +// zero, but it needs the right amount of nesting. +#if defined(__FreeBSD__) +#define ZERO_COND_INITIALIZER \ + { 0 } +#elif defined(__APPLE__) +#define ZERO_COND_INITIALIZER \ + { \ + { 0 } \ + } +#else // __linux__, at least +#define ZERO_COND_INITIALIZER \ + { \ + { \ + { 0 } \ + } \ + } +#endif + +static inline void toku_mutexattr_init(toku_pthread_mutexattr_t *attr) { int r = pthread_mutexattr_init(attr); assert_zero(r); } @@ -138,61 +192,8 @@ toku_mutexattr_destroy(toku_pthread_mutexattr_t *attr) { assert_zero(r); } -static inline void -toku_mutex_destroy(toku_mutex_t *mutex) { #if TOKU_PTHREAD_DEBUG - invariant(mutex->valid); - mutex->valid = false; - invariant(!mutex->locked); -#endif - int r = pthread_mutex_destroy(&mutex->pmutex); - assert_zero(r); -} - -static inline void -toku_mutex_lock(toku_mutex_t *mutex) { - int r = pthread_mutex_lock(&mutex->pmutex); - assert_zero(r); -#if TOKU_PTHREAD_DEBUG - invariant(mutex->valid); - invariant(!mutex->locked); - invariant(mutex->owner == 0); - mutex->locked = true; - mutex->owner = pthread_self(); -#endif -} - -static inline int -toku_mutex_trylock(toku_mutex_t *mutex) { - int r = pthread_mutex_trylock(&mutex->pmutex); -#if TOKU_PTHREAD_DEBUG - if (r == 0) { - invariant(mutex->valid); - invariant(!mutex->locked); - invariant(mutex->owner == 0); - mutex->locked = true; - mutex->owner = pthread_self(); - } -#endif - return r; -} - -static inline void -toku_mutex_unlock(toku_mutex_t *mutex) { -#if TOKU_PTHREAD_DEBUG - invariant(mutex->owner == pthread_self()); - invariant(mutex->valid); - invariant(mutex->locked); - mutex->locked = false; - mutex->owner = 0; -#endif - int r = pthread_mutex_unlock(&mutex->pmutex); - assert_zero(r); -} - -#if TOKU_PTHREAD_DEBUG -static inline void -toku_mutex_assert_locked(const toku_mutex_t *mutex) { +static inline void toku_mutex_assert_locked(const toku_mutex_t *mutex) { invariant(mutex->locked); invariant(mutex->owner == pthread_self()); } @@ -217,40 +218,123 @@ toku_mutex_assert_unlocked(toku_mutex_t *mutex) { invariant(!mutex->locked); } #else -static inline void -toku_mutex_assert_unlocked(toku_mutex_t *mutex __attribute__((unused))) { +static inline void toku_mutex_assert_unlocked(toku_mutex_t *mutex + __attribute__((unused))) {} +#endif + +#define toku_mutex_lock(M) \ + toku_mutex_lock_with_source_location(M, __FILE__, __LINE__) + +static inline void toku_cond_init(toku_cond_t *cond, + const toku_pthread_condattr_t *attr) { + int r = pthread_cond_init(&cond->pcond, attr); + assert_zero(r); +} + +#define toku_mutex_trylock(M) \ + toku_mutex_trylock_with_source_location(M, __FILE__, __LINE__) + +inline void toku_mutex_unlock(toku_mutex_t *mutex) { +#if TOKU_PTHREAD_DEBUG + invariant(mutex->owner == pthread_self()); + invariant(mutex->valid); + invariant(mutex->locked); + mutex->locked = false; + mutex->owner = 0; +#endif + toku_instr_mutex_unlock(mutex->psi_mutex); + int r = pthread_mutex_unlock(&mutex->pmutex); + assert_zero(r); } + +inline void toku_mutex_lock_with_source_location(toku_mutex_t *mutex, + const char *src_file, + int src_line) { + + toku_mutex_instrumentation mutex_instr; + toku_instr_mutex_lock_start(mutex_instr, *mutex, src_file, src_line); + + const int r = pthread_mutex_lock(&mutex->pmutex); + toku_instr_mutex_lock_end(mutex_instr, r); + + assert_zero(r); +#if TOKU_PTHREAD_DEBUG + invariant(mutex->valid); + invariant(!mutex->locked); + invariant(mutex->owner == 0); + mutex->locked = true; + mutex->owner = pthread_self(); #endif +} -typedef struct toku_cond { - pthread_cond_t pcond; -} toku_cond_t; +inline int toku_mutex_trylock_with_source_location(toku_mutex_t *mutex, + const char *src_file, + int src_line) { -// Same considerations as for ZERO_MUTEX_INITIALIZER apply -#define ZERO_COND_INITIALIZER {} + toku_mutex_instrumentation mutex_instr; + toku_instr_mutex_trylock_start(mutex_instr, *mutex, src_file, src_line); -#define TOKU_COND_INITIALIZER {PTHREAD_COND_INITIALIZER} + const int r = pthread_mutex_lock(&mutex->pmutex); + toku_instr_mutex_lock_end(mutex_instr, r); -static inline void -toku_cond_init(toku_cond_t *cond, const toku_pthread_condattr_t *attr) { +#if TOKU_PTHREAD_DEBUG + if (r == 0) { + invariant(mutex->valid); + invariant(!mutex->locked); + invariant(mutex->owner == 0); + mutex->locked = true; + mutex->owner = pthread_self(); + } +#endif + return r; +} + +#define toku_cond_wait(C, M) \ + toku_cond_wait_with_source_location(C, M, __FILE__, __LINE__) + +#define toku_cond_timedwait(C, M, W) \ + toku_cond_timedwait_with_source_location(C, M, W, __FILE__, __LINE__) + +inline void toku_cond_init(const toku_instr_key &key, + toku_cond_t *cond, + const pthread_condattr_t *attr) { + toku_instr_cond_init(key, *cond); int r = pthread_cond_init(&cond->pcond, attr); assert_zero(r); } -static inline void -toku_cond_destroy(toku_cond_t *cond) { +inline void toku_cond_destroy(toku_cond_t *cond) { + toku_instr_cond_destroy(cond->psi_cond); int r = pthread_cond_destroy(&cond->pcond); assert_zero(r); } -static inline void -toku_cond_wait(toku_cond_t *cond, toku_mutex_t *mutex) { +inline void toku_cond_wait_with_source_location(toku_cond_t *cond, + toku_mutex_t *mutex, + const char *src_file, + uint src_line) { + #if TOKU_PTHREAD_DEBUG invariant(mutex->locked); mutex->locked = false; mutex->owner = 0; #endif - int r = pthread_cond_wait(&cond->pcond, &mutex->pmutex); + + /* Instrumentation start */ + toku_cond_instrumentation cond_instr; + toku_instr_cond_wait_start(cond_instr, + toku_instr_cond_op::cond_wait, + *cond, + *mutex, + src_file, + src_line); + + /* Instrumented code */ + const int r = pthread_cond_wait(&cond->pcond, &mutex->pmutex); + + /* Instrumentation end */ + toku_instr_cond_wait_end(cond_instr, r); + assert_zero(r); #if TOKU_PTHREAD_DEBUG invariant(!mutex->locked); @@ -259,14 +343,33 @@ toku_cond_wait(toku_cond_t *cond, toku_mutex_t *mutex) { #endif } -static inline int -toku_cond_timedwait(toku_cond_t *cond, toku_mutex_t *mutex, toku_timespec_t *wakeup_at) { +inline int toku_cond_timedwait_with_source_location(toku_cond_t *cond, + toku_mutex_t *mutex, + toku_timespec_t *wakeup_at, + const char *src_file, + uint src_line) { #if TOKU_PTHREAD_DEBUG invariant(mutex->locked); mutex->locked = false; mutex->owner = 0; #endif - int r = pthread_cond_timedwait(&cond->pcond, &mutex->pmutex, wakeup_at); + + /* Instrumentation start */ + toku_cond_instrumentation cond_instr; + toku_instr_cond_wait_start(cond_instr, + toku_instr_cond_op::cond_timedwait, + *cond, + *mutex, + src_file, + src_line); + + /* Instrumented code */ + const int r = pthread_cond_timedwait( + &cond->pcond, &mutex->pmutex, wakeup_at); + + /* Instrumentation end */ + toku_instr_cond_wait_end(cond_instr, r); + #if TOKU_PTHREAD_DEBUG invariant(!mutex->locked); mutex->locked = true; @@ -275,69 +378,116 @@ toku_cond_timedwait(toku_cond_t *cond, toku_mutex_t *mutex, toku_timespec_t *wak return r; } -static inline void -toku_cond_signal(toku_cond_t *cond) { - int r = pthread_cond_signal(&cond->pcond); +inline void toku_cond_signal(toku_cond_t *cond) { + toku_instr_cond_signal(*cond); + const int r = pthread_cond_signal(&cond->pcond); assert_zero(r); } -static inline void -toku_cond_broadcast(toku_cond_t *cond) { - int r =pthread_cond_broadcast(&cond->pcond); +inline void toku_cond_broadcast(toku_cond_t *cond) { + toku_instr_cond_broadcast(*cond); + const int r = pthread_cond_broadcast(&cond->pcond); assert_zero(r); } -int -toku_pthread_yield(void) __attribute__((__visibility__("default"))); - -static inline toku_pthread_t -toku_pthread_self(void) { - return pthread_self(); +inline void toku_mutex_init(const toku_instr_key &key, + toku_mutex_t *mutex, + const toku_pthread_mutexattr_t *attr) { +#if TOKU_PTHREAD_DEBUG + mutex->valid = true; +#endif + toku_instr_mutex_init(key, *mutex); + const int r = pthread_mutex_init(&mutex->pmutex, attr); + assert_zero(r); +#if TOKU_PTHREAD_DEBUG + mutex->locked = false; + invariant(mutex->valid); + mutex->valid = true; + mutex->owner = 0; +#endif } -static inline void -toku_pthread_rwlock_init(toku_pthread_rwlock_t *__restrict rwlock, const toku_pthread_rwlockattr_t *__restrict attr) { - int r = pthread_rwlock_init(rwlock, attr); +inline void toku_mutex_destroy(toku_mutex_t *mutex) { +#if TOKU_PTHREAD_DEBUG + invariant(mutex->valid); + mutex->valid = false; + invariant(!mutex->locked); +#endif + toku_instr_mutex_destroy(mutex->psi_mutex); + int r = pthread_mutex_destroy(&mutex->pmutex); assert_zero(r); } -static inline void -toku_pthread_rwlock_destroy(toku_pthread_rwlock_t *rwlock) { - int r = pthread_rwlock_destroy(rwlock); +#define toku_pthread_rwlock_rdlock(RW) \ + toku_pthread_rwlock_rdlock_with_source_location(RW, __FILE__, __LINE__) + +#define toku_pthread_rwlock_wrlock(RW) \ + toku_pthread_rwlock_wrlock_with_source_location(RW, __FILE__, __LINE__) + +inline void toku_pthread_rwlock_init( + const toku_instr_key &key, + toku_pthread_rwlock_t *__restrict rwlock, + const toku_pthread_rwlockattr_t *__restrict attr) { + toku_instr_rwlock_init(key, *rwlock); + int r = pthread_rwlock_init(&rwlock->rwlock, attr); assert_zero(r); } -static inline void -toku_pthread_rwlock_rdlock(toku_pthread_rwlock_t *rwlock) { - int r = pthread_rwlock_rdlock(rwlock); +inline void toku_pthread_rwlock_destroy(toku_pthread_rwlock_t *rwlock) { + toku_instr_rwlock_destroy(rwlock->psi_rwlock); + int r = pthread_rwlock_destroy(&rwlock->rwlock); assert_zero(r); } -static inline void -toku_pthread_rwlock_rdunlock(toku_pthread_rwlock_t *rwlock) { - int r = pthread_rwlock_unlock(rwlock); +inline void toku_pthread_rwlock_rdlock_with_source_location( + toku_pthread_rwlock_t *rwlock, + const char *src_file, + uint src_line) { + + /* Instrumentation start */ + toku_rwlock_instrumentation rwlock_instr; + toku_instr_rwlock_rdlock_wait_start( + rwlock_instr, *rwlock, src_file, src_line); + /* Instrumented code */ + const int r = pthread_rwlock_rdlock(&rwlock->rwlock); + + /* Instrumentation end */ + toku_instr_rwlock_rdlock_wait_end(rwlock_instr, r); + assert_zero(r); } -static inline void -toku_pthread_rwlock_wrlock(toku_pthread_rwlock_t *rwlock) { - int r = pthread_rwlock_wrlock(rwlock); +inline void toku_pthread_rwlock_wrlock_with_source_location( + toku_pthread_rwlock_t *rwlock, + const char *src_file, + uint src_line) { + + /* Instrumentation start */ + toku_rwlock_instrumentation rwlock_instr; + toku_instr_rwlock_wrlock_wait_start( + rwlock_instr, *rwlock, src_file, src_line); + /* Instrumented code */ + const int r = pthread_rwlock_wrlock(&rwlock->rwlock); + + /* Instrumentation end */ + toku_instr_rwlock_wrlock_wait_end(rwlock_instr, r); + assert_zero(r); } -static inline void -toku_pthread_rwlock_wrunlock(toku_pthread_rwlock_t *rwlock) { - int r = pthread_rwlock_unlock(rwlock); +inline void toku_pthread_rwlock_rdunlock(toku_pthread_rwlock_t *rwlock) { + toku_instr_rwlock_unlock(*rwlock); + const int r = pthread_rwlock_unlock(&rwlock->rwlock); assert_zero(r); } -static inline int -toku_pthread_create(toku_pthread_t *thread, const toku_pthread_attr_t *attr, void *(*start_function)(void *), void *arg) { - return pthread_create(thread, attr, start_function, arg); +inline void toku_pthread_rwlock_wrunlock(toku_pthread_rwlock_t *rwlock) { + toku_instr_rwlock_unlock(*rwlock); + const int r = pthread_rwlock_unlock(&rwlock->rwlock); + assert_zero(r); } -static inline int -toku_pthread_join(toku_pthread_t thread, void **value_ptr) { +static inline int toku_pthread_join(toku_pthread_t thread, void **value_ptr) { return pthread_join(thread, value_ptr); } @@ -361,7 +511,15 @@ toku_pthread_getspecific(toku_pthread_key_t key) { return pthread_getspecific(key); } -static inline int -toku_pthread_setspecific(toku_pthread_key_t key, void *data) { +static inline int toku_pthread_setspecific(toku_pthread_key_t key, void *data) { return pthread_setspecific(key, data); } + +int toku_pthread_yield(void) __attribute__((__visibility__("default"))); + +static inline toku_pthread_t toku_pthread_self(void) { return pthread_self(); } + +static inline void *toku_pthread_done(void *exit_value) { + toku_instr_delete_current_thread(); + pthread_exit(exit_value); +} diff --git a/storage/tokudb/PerconaFT/src/indexer-undo-do.cc b/storage/tokudb/PerconaFT/src/indexer-undo-do.cc index 4c7f5336161..cc86402751b 100644 --- a/storage/tokudb/PerconaFT/src/indexer-undo-do.cc +++ b/storage/tokudb/PerconaFT/src/indexer-undo-do.cc @@ -571,6 +571,7 @@ indexer_ft_delete_committed(DB_INDEXER *indexer, DB *hotdb, DBT *hotkey, XIDS xi oldest_referenced_xid_estimate, true); toku_ft_send_delete(db_struct_i(hotdb)->ft_handle, hotkey, xids, &gc_info); + toku_ft_adjust_logical_row_count(db_struct_i(hotdb)->ft_handle->ft, -1); } } return result; @@ -616,6 +617,7 @@ indexer_ft_insert_committed(DB_INDEXER *indexer, DB *hotdb, DBT *hotkey, DBT *ho oldest_referenced_xid_estimate, true); toku_ft_send_insert(db_struct_i(hotdb)->ft_handle, hotkey, hotval, xids, FT_INSERT, &gc_info); + toku_ft_adjust_logical_row_count(db_struct_i(hotdb)->ft_handle->ft, 1); } } return result; diff --git a/storage/tokudb/PerconaFT/src/indexer.cc b/storage/tokudb/PerconaFT/src/indexer.cc index b475b08beb5..044ffac917c 100644 --- a/storage/tokudb/PerconaFT/src/indexer.cc +++ b/storage/tokudb/PerconaFT/src/indexer.cc @@ -253,16 +253,21 @@ toku_indexer_create_indexer(DB_ENV *env, indexer->set_error_callback = toku_indexer_set_error_callback; indexer->set_poll_function = toku_indexer_set_poll_function; indexer->build = build_index; - indexer->close = close_indexer; - indexer->abort = abort_indexer; - - toku_mutex_init(&indexer->i->indexer_lock, NULL); - toku_mutex_init(&indexer->i->indexer_estimate_lock, NULL); + indexer->close = close_indexer; + indexer->abort = abort_indexer; + + toku_mutex_init( + *indexer_i_indexer_lock_mutex_key, &indexer->i->indexer_lock, nullptr); + toku_mutex_init(*indexer_i_indexer_estimate_lock_mutex_key, + &indexer->i->indexer_estimate_lock, + nullptr); toku_init_dbt(&indexer->i->position_estimate); // - // create and close a dummy loader to get redirection going for the hot indexer - // This way, if the hot index aborts, but other transactions have references to the + // create and close a dummy loader to get redirection going for the hot + // indexer + // This way, if the hot index aborts, but other transactions have references + // to the // underlying FT, then those transactions can do dummy operations on the FT // while the DB gets redirected back to an empty dictionary // diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-first-empty.cc b/storage/tokudb/PerconaFT/src/tests/blocking-first-empty.cc index d9d865254f1..3b53911e614 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-first-empty.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-first-empty.cc @@ -99,12 +99,14 @@ static void *blocking_first_thread(void *arg) { static void run_test(DB_ENV *db_env, DB *db, int nthreads, uint64_t nrows, long sleeptime) { int r; toku_pthread_t tids[nthreads]; - struct blocking_first_args a = { db_env, db, nrows, sleeptime }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_first_thread, &a); assert(r == 0); + struct blocking_first_args a = {db_env, db, nrows, sleeptime}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, blocking_first_thread, &a); + assert(r == 0); } blocking_first(db_env, db, nrows, sleeptime); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-first.cc b/storage/tokudb/PerconaFT/src/tests/blocking-first.cc index 9f3f8f4eb6a..c104eabd6c3 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-first.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-first.cc @@ -116,12 +116,14 @@ static void *blocking_first_thread(void *arg) { static void run_test(DB_ENV *db_env, DB *db, int nthreads, uint64_t nrows, long sleeptime) { int r; toku_pthread_t tids[nthreads]; - struct blocking_first_args a = { db_env, db, nrows, sleeptime }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_first_thread, &a); assert(r == 0); + struct blocking_first_args a = {db_env, db, nrows, sleeptime}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, blocking_first_thread, &a); + assert(r == 0); } blocking_first(db_env, db, nrows, sleeptime); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-last.cc b/storage/tokudb/PerconaFT/src/tests/blocking-last.cc index a62d83eb46f..3a702e3f115 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-last.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-last.cc @@ -116,12 +116,14 @@ static void *blocking_last_thread(void *arg) { static void run_test(DB_ENV *db_env, DB *db, int nthreads, uint64_t nrows, long sleeptime) { int r; toku_pthread_t tids[nthreads]; - struct blocking_last_args a = { db_env, db, nrows, sleeptime }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_last_thread, &a); assert(r == 0); + struct blocking_last_args a = {db_env, db, nrows, sleeptime}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, blocking_last_thread, &a); + assert(r == 0); } blocking_last(db_env, db, nrows, sleeptime); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-next-prev-deadlock.cc b/storage/tokudb/PerconaFT/src/tests/blocking-next-prev-deadlock.cc index bd5697ba526..781708cc627 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-next-prev-deadlock.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-next-prev-deadlock.cc @@ -181,12 +181,14 @@ static void *blocking_next_thread(void *arg) { static void run_test(DB_ENV *db_env, DB *db, int nthreads, uint64_t nrows, long sleeptime) { int r; toku_pthread_t tids[nthreads]; - struct blocking_next_args a = { db_env, db, nrows, sleeptime }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_next_thread, &a); assert(r == 0); + struct blocking_next_args a = {db_env, db, nrows, sleeptime}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, blocking_next_thread, &a); + assert(r == 0); } blocking_prev(db_env, db, nrows, sleeptime); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-next-prev.cc b/storage/tokudb/PerconaFT/src/tests/blocking-next-prev.cc index 729473bb7cf..aa179e88d76 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-next-prev.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-next-prev.cc @@ -188,12 +188,14 @@ static void *blocking_next_thread(void *arg) { static void run_test(DB_ENV *db_env, DB *db, int nthreads, uint64_t nrows, long sleeptime) { int r; toku_pthread_t tids[nthreads]; - struct blocking_next_args a = { db_env, db, nrows, sleeptime }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_next_thread, &a); assert(r == 0); + struct blocking_next_args a = {db_env, db, nrows, sleeptime}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, blocking_next_thread, &a); + assert(r == 0); } blocking_prev(db_env, db, nrows, sleeptime); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-prelock-range.cc b/storage/tokudb/PerconaFT/src/tests/blocking-prelock-range.cc index 8821b39aa8a..38875a2f8ec 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-prelock-range.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-prelock-range.cc @@ -140,12 +140,17 @@ int test_main(int argc, char * const argv[]) { r = db->open(db, NULL, db_filename, NULL, DB_BTREE, DB_CREATE|DB_AUTO_COMMIT|DB_THREAD, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0); toku_pthread_t tids[nthreads]; - struct blocking_range_lock_args a = { db_env, db, nrows, sleeptime }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_range_lock_thread, &a); assert(r == 0); + struct blocking_range_lock_args a = {db_env, db, nrows, sleeptime}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create(toku_uninstrumented, + &tids[i], + nullptr, + blocking_range_lock_thread, + &a); + assert(r == 0); } blocking_range_lock(db_env, db, nrows, sleeptime); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-put-timeout.cc b/storage/tokudb/PerconaFT/src/tests/blocking-put-timeout.cc index a31e173fd83..bf4a8a24f47 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-put-timeout.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-put-timeout.cc @@ -57,8 +57,8 @@ struct test_seq { static void test_seq_init(struct test_seq *seq) { seq->state = 0; - toku_mutex_init(&seq->lock, NULL); - toku_cond_init(&seq->cv, NULL); + toku_mutex_init(toku_uninstrumented, &seq->lock, nullptr); + toku_cond_init(toku_uninstrumented, &seq->cv, nullptr); } static void test_seq_destroy(struct test_seq *seq) { @@ -172,13 +172,18 @@ int test_main(int argc, char * const argv[]) { r = db->open(db, NULL, db_filename, NULL, DB_BTREE, DB_CREATE|DB_AUTO_COMMIT|DB_THREAD, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0); // run test - struct test_seq seq; ZERO_STRUCT(seq); test_seq_init(&seq); + struct test_seq seq; + ZERO_STRUCT(seq); + test_seq_init(&seq); toku_pthread_t t_a_id; - struct t_a_args t_a_args = { db_env, db, &seq }; - r = toku_pthread_create(&t_a_id, NULL, t_a_thread, &t_a_args); assert(r == 0); + struct t_a_args t_a_args = {db_env, db, &seq}; + r = toku_pthread_create( + toku_uninstrumented, &t_a_id, nullptr, t_a_thread, &t_a_args); + assert(r == 0); t_b(db_env, db, &seq); void *ret; - r = toku_pthread_join(t_a_id, &ret); assert(r == 0); + r = toku_pthread_join(t_a_id, &ret); + assert(r == 0); test_seq_destroy(&seq); // close env diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-put-wakeup.cc b/storage/tokudb/PerconaFT/src/tests/blocking-put-wakeup.cc index 615cdb5d17c..dba7962de35 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-put-wakeup.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-put-wakeup.cc @@ -58,8 +58,8 @@ struct test_seq { static void test_seq_init(struct test_seq *seq) { seq->state = 0; - toku_mutex_init(&seq->lock, NULL); - toku_cond_init(&seq->cv, NULL); + toku_mutex_init(toku_uninstrumented, &seq->lock, nullptr); + toku_cond_init(toku_uninstrumented, &seq->cv, nullptr); } static void test_seq_destroy(struct test_seq *seq) { @@ -167,13 +167,18 @@ int test_main(int argc, char * const argv[]) { r = db->open(db, NULL, db_filename, NULL, DB_BTREE, DB_CREATE|DB_AUTO_COMMIT|DB_THREAD, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0); // run test - struct test_seq seq; ZERO_STRUCT(seq); test_seq_init(&seq); + struct test_seq seq; + ZERO_STRUCT(seq); + test_seq_init(&seq); toku_pthread_t t_a_id; - struct t_a_args t_a_args = { db_env, db, &seq }; - r = toku_pthread_create(&t_a_id, NULL, t_a_thread, &t_a_args); assert(r == 0); + struct t_a_args t_a_args = {db_env, db, &seq}; + r = toku_pthread_create( + toku_uninstrumented, &t_a_id, nullptr, t_a_thread, &t_a_args); + assert(r == 0); t_b(db_env, db, &seq); void *ret; - r = toku_pthread_join(t_a_id, &ret); assert(r == 0); + r = toku_pthread_join(t_a_id, &ret); + assert(r == 0); test_seq_destroy(&seq); // close env diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-put.cc b/storage/tokudb/PerconaFT/src/tests/blocking-put.cc index 0fa56325007..95481062483 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-put.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-put.cc @@ -139,12 +139,14 @@ int test_main(int argc, char * const argv[]) { r = db->open(db, NULL, db_filename, NULL, DB_BTREE, DB_CREATE|DB_AUTO_COMMIT|DB_THREAD, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0); toku_pthread_t tids[nthreads]; - struct blocking_put_args a = { db_env, db, nrows, sleeptime }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_put_thread, &a); assert(r == 0); + struct blocking_put_args a = {db_env, db, nrows, sleeptime}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, blocking_put_thread, &a); + assert(r == 0); } blocking_put(db_env, db, nrows, sleeptime); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-set-range-0.cc b/storage/tokudb/PerconaFT/src/tests/blocking-set-range-0.cc index a0e03ab3293..7c2e7b0fb26 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-set-range-0.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-set-range-0.cc @@ -126,12 +126,15 @@ static void *blocking_set_range_thread(void *arg) { static void run_test(DB_ENV *db_env, DB *db, int nthreads, uint64_t nrows, long sleeptime, uint64_t the_key) { int r; toku_pthread_t tids[nthreads]; - struct blocking_set_range_args a = { db_env, db, nrows, sleeptime, the_key }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_set_range_thread, &a); assert(r == 0); + struct blocking_set_range_args a = {db_env, db, nrows, sleeptime, the_key}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, + blocking_set_range_thread, &a); + assert(r == 0); } blocking_set_range(db_env, db, nrows, sleeptime, the_key); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-set-range-n.cc b/storage/tokudb/PerconaFT/src/tests/blocking-set-range-n.cc index 056d74dbdd2..54a5846eb5e 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-set-range-n.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-set-range-n.cc @@ -121,12 +121,15 @@ static void *blocking_set_range_thread(void *arg) { static void run_test(DB_ENV *db_env, DB *db, int nthreads, uint64_t nrows, long sleeptime, uint64_t the_key) { int r; toku_pthread_t tids[nthreads]; - struct blocking_set_range_args a = { db_env, db, nrows, sleeptime, the_key }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_set_range_thread, &a); assert(r == 0); + struct blocking_set_range_args a = {db_env, db, nrows, sleeptime, the_key}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, + blocking_set_range_thread, &a); + assert(r == 0); } blocking_set_range(db_env, db, nrows, sleeptime, the_key); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-set-range-reverse-0.cc b/storage/tokudb/PerconaFT/src/tests/blocking-set-range-reverse-0.cc index 1e7fca85bff..59e582547bf 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-set-range-reverse-0.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-set-range-reverse-0.cc @@ -126,12 +126,15 @@ static void *blocking_set_range_thread(void *arg) { static void run_test(DB_ENV *db_env, DB *db, int nthreads, uint64_t nrows, long sleeptime, uint64_t the_key) { int r; toku_pthread_t tids[nthreads]; - struct blocking_set_range_args a = { db_env, db, nrows, sleeptime, the_key }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_set_range_thread, &a); assert(r == 0); + struct blocking_set_range_args a = {db_env, db, nrows, sleeptime, the_key}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, + blocking_set_range_thread, &a); + assert(r == 0); } blocking_set_range(db_env, db, nrows, sleeptime, the_key); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-set.cc b/storage/tokudb/PerconaFT/src/tests/blocking-set.cc index ba64989842a..aa433c87be1 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-set.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-set.cc @@ -182,12 +182,14 @@ int test_main(int argc, char * const argv[]) { populate(db_env, db, nrows); toku_pthread_t tids[nthreads]; - struct blocking_set_args a = { db_env, db, nrows, sleeptime }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_set_thread, &a); assert(r == 0); + struct blocking_set_args a = {db_env, db, nrows, sleeptime}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, blocking_set_thread, &a); + assert(r == 0); } blocking_set(db_env, db, nrows, sleeptime); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/blocking-table-lock.cc b/storage/tokudb/PerconaFT/src/tests/blocking-table-lock.cc index 9ae33c56621..0953a4e80de 100644 --- a/storage/tokudb/PerconaFT/src/tests/blocking-table-lock.cc +++ b/storage/tokudb/PerconaFT/src/tests/blocking-table-lock.cc @@ -133,12 +133,17 @@ int test_main(int argc, char * const argv[]) { r = db->open(db, NULL, db_filename, NULL, DB_BTREE, DB_CREATE|DB_AUTO_COMMIT|DB_THREAD, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); assert(r == 0); toku_pthread_t tids[nthreads]; - struct blocking_table_lock_args a = { db_env, db, nrows, sleeptime }; - for (int i = 0; i < nthreads-1; i++) { - r = toku_pthread_create(&tids[i], NULL, blocking_table_lock_thread, &a); assert(r == 0); + struct blocking_table_lock_args a = {db_env, db, nrows, sleeptime}; + for (int i = 0; i < nthreads - 1; i++) { + r = toku_pthread_create(toku_uninstrumented, + &tids[i], + nullptr, + blocking_table_lock_thread, + &a); + assert(r == 0); } blocking_table_lock(db_env, db, nrows, sleeptime); - for (int i = 0; i < nthreads-1; i++) { + for (int i = 0; i < nthreads - 1; i++) { void *ret; r = toku_pthread_join(tids[i], &ret); assert(r == 0); } diff --git a/storage/tokudb/PerconaFT/src/tests/checkpoint_fairness.cc b/storage/tokudb/PerconaFT/src/tests/checkpoint_fairness.cc index be82f8c352f..f62dfbc76d3 100644 --- a/storage/tokudb/PerconaFT/src/tests/checkpoint_fairness.cc +++ b/storage/tokudb/PerconaFT/src/tests/checkpoint_fairness.cc @@ -113,10 +113,14 @@ int test_main(int argc, char * const argv[]) { { int chk_r = db->open(db, NULL, "db", NULL, DB_BTREE, DB_CREATE|DB_AUTO_COMMIT, 0666); CKERR(chk_r); } pthread_t thds[n_threads]; - int ids[n_threads]; - for (int i=0; i<n_threads; i++) { - ids[i]=i; - { int chk_r = toku_pthread_create(&thds[i], NULL, start_txns, &ids[i]); CKERR(chk_r); } + int ids[n_threads]; + for (int i = 0; i < n_threads; i++) { + ids[i] = i; + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &thds[i], nullptr, start_txns, &ids[i]); + CKERR(chk_r); + } } start_checkpoints(); diff --git a/storage/tokudb/PerconaFT/src/tests/checkpoint_stress.cc b/storage/tokudb/PerconaFT/src/tests/checkpoint_stress.cc index 221471a8045..135a9843ce4 100644 --- a/storage/tokudb/PerconaFT/src/tests/checkpoint_stress.cc +++ b/storage/tokudb/PerconaFT/src/tests/checkpoint_stress.cc @@ -271,24 +271,29 @@ run_test (int iter, int die) { } // take checkpoint (all dictionaries) - snapshot(NULL, 1); + snapshot(NULL, 1); if (die) { - // separate thread will perform random acts on other dictionaries (not 0) - int r = toku_pthread_create(&thread, 0, random_acts, (void *) dictionaries); - CKERR(r); - // this thead will scribble over dictionary 0 before crash to verify that - // post-checkpoint inserts are not in the database - DB* db = dictionaries[0].db; - if (iter & 1) - scribble(db, iter); - else - thin_out(db, iter); - uint32_t delay = myrandom(); - delay &= 0xFFF; // select lower 12 bits, shifted up 8 for random number ... - delay = delay << 8; // ... uniformly distributed between 0 and 1M ... - usleep(delay); // ... to sleep up to one second (1M usec) - drop_dead(); + // separate thread will perform random acts on other dictionaries (not + // 0) + int r = toku_pthread_create( + toku_uninstrumented, &thread, nullptr, + random_acts, static_cast<void*>(dictionaries)); + CKERR(r); + // this thead will scribble over dictionary 0 before crash to verify + // that + // post-checkpoint inserts are not in the database + DB* db = dictionaries[0].db; + if (iter & 1) + scribble(db, iter); + else + thin_out(db, iter); + uint32_t delay = myrandom(); + delay &= + 0xFFF; // select lower 12 bits, shifted up 8 for random number ... + delay = delay << 8; // ... uniformly distributed between 0 and 1M ... + usleep(delay); // ... to sleep up to one second (1M usec) + drop_dead(); } else { for (i = 0; i < NUM_DICTIONARIES; i++) { diff --git a/storage/tokudb/PerconaFT/src/tests/db-put-simple-deadlock-threads.cc b/storage/tokudb/PerconaFT/src/tests/db-put-simple-deadlock-threads.cc index ada46bd7516..e5bcc6af7bb 100644 --- a/storage/tokudb/PerconaFT/src/tests/db-put-simple-deadlock-threads.cc +++ b/storage/tokudb/PerconaFT/src/tests/db-put-simple-deadlock-threads.cc @@ -57,8 +57,8 @@ struct test_seq { static void test_seq_init(struct test_seq *seq) { seq->state = 0; - toku_mutex_init(&seq->lock, NULL); - toku_cond_init(&seq->cv, NULL); + toku_mutex_init(toku_uninstrumented, &seq->lock, nullptr); + toku_cond_init(toku_uninstrumented, &seq->cv, nullptr); } static void test_seq_destroy(struct test_seq *seq) { @@ -146,8 +146,9 @@ static void simple_deadlock(DB_ENV *db_env, DB *db, int do_txn, int n) { struct test_seq test_seq; ZERO_STRUCT(test_seq); test_seq_init(&test_seq); toku_pthread_t tid; - struct run_txn_b_arg arg = { &test_seq, txn_b, db, n}; - r = toku_pthread_create(&tid, NULL, run_txn_b, &arg); + struct run_txn_b_arg arg = {&test_seq, txn_b, db, n}; + r = toku_pthread_create( + toku_uninstrumented, &tid, nullptr, run_txn_b, &arg); test_seq_sleep(&test_seq, 0); insert_row(db, txn_a, htonl(0), 0, 0); diff --git a/storage/tokudb/PerconaFT/src/tests/db-put-simple-lockwait.cc b/storage/tokudb/PerconaFT/src/tests/db-put-simple-lockwait.cc index 365ea39eced..0fbe851532e 100644 --- a/storage/tokudb/PerconaFT/src/tests/db-put-simple-lockwait.cc +++ b/storage/tokudb/PerconaFT/src/tests/db-put-simple-lockwait.cc @@ -95,10 +95,11 @@ static void simple_lockwait(DB_ENV *db_env, DB *db, int do_txn, int nrows, int n insert_row(db, txns[0], htonl(0), 0, 0); toku_pthread_t tids[ntxns]; - for (int i = 1 ; i < ntxns; i++) { + for (int i = 1; i < ntxns; i++) { struct insert_one_arg *XMALLOC(arg); - *arg = (struct insert_one_arg) { txns[i], db}; - r = toku_pthread_create(&tids[i], NULL, insert_one, arg); + *arg = (struct insert_one_arg){txns[i], db}; + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, insert_one, arg); } sleep(10); diff --git a/storage/tokudb/PerconaFT/src/tests/db-put-update-deadlock.cc b/storage/tokudb/PerconaFT/src/tests/db-put-update-deadlock.cc index 3660f11d1bd..7a968058d7f 100644 --- a/storage/tokudb/PerconaFT/src/tests/db-put-update-deadlock.cc +++ b/storage/tokudb/PerconaFT/src/tests/db-put-update-deadlock.cc @@ -128,10 +128,12 @@ static void update_deadlock(DB_ENV *db_env, DB *db, int do_txn, int nrows, int n // get write locks toku_pthread_t tids[ntxns]; - for (int i = 0 ; i < ntxns; i++) { + for (int i = 0; i < ntxns; i++) { struct write_one_arg *XMALLOC(arg); - *arg = (struct write_one_arg) { txns[i], db, (int) htonl((i + 1) % ntxns), 0}; - r = toku_pthread_create(&tids[i], NULL, write_one_f, arg); + *arg = + (struct write_one_arg){txns[i], db, (int)htonl((i + 1) % ntxns), 0}; + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, write_one_f, arg); } #else // get read locks @@ -141,10 +143,11 @@ static void update_deadlock(DB_ENV *db_env, DB *db, int do_txn, int nrows, int n // get write locks toku_pthread_t tids[ntxns]; - for (int i = 0 ; i < ntxns; i++) { + for (int i = 0; i < ntxns; i++) { struct write_one_arg *XMALLOC(arg); - *arg = (struct write_one_arg) { txns[i], db, (int) htonl(0), 0}; - r = toku_pthread_create(&tids[i], NULL, write_one_f, arg); + *arg = (struct write_one_arg){txns[i], db, (int)htonl(0), 0}; + r = toku_pthread_create( + toku_uninstrumented, &tids[i], nullptr, write_one_f, arg); } #endif diff --git a/storage/tokudb/PerconaFT/src/tests/filesize.cc b/storage/tokudb/PerconaFT/src/tests/filesize.cc index 6ab22245e68..9dfeea131c6 100644 --- a/storage/tokudb/PerconaFT/src/tests/filesize.cc +++ b/storage/tokudb/PerconaFT/src/tests/filesize.cc @@ -170,11 +170,9 @@ get_file_pathname(void) { if (verbose) printf("path = %s\n", path); } - -static int -getsizeM(void) { +static int getsizeM(void) { toku_struct_stat buf; - int r = toku_stat(path, &buf); + int r = toku_stat(path, &buf, toku_uninstrumented); CKERR(r); int sizeM = (int)buf.st_size >> 20; check_fragmentation(); diff --git a/storage/tokudb/PerconaFT/src/tests/hotindexer-bw.cc b/storage/tokudb/PerconaFT/src/tests/hotindexer-bw.cc index 82471f30e45..5336bc3329f 100644 --- a/storage/tokudb/PerconaFT/src/tests/hotindexer-bw.cc +++ b/storage/tokudb/PerconaFT/src/tests/hotindexer-bw.cc @@ -302,12 +302,19 @@ static void test_indexer(DB *src, DB **dbs) CKERR(r); toku_mutex_unlock(&put_lock); - // start threads doing additional inserts - no lock issues since indexer already created - r = toku_pthread_create(&client_threads[0], 0, client, (void *)&client_specs[0]); CKERR(r); -// r = toku_pthread_create(&client_threads[1], 0, client, (void *)&client_specs[1]); CKERR(r); + // start threads doing additional inserts - no lock issues since indexer + // already created + r = toku_pthread_create(toku_uninstrumented, + &client_threads[0], + nullptr, + client, + static_cast<void *>(&client_specs[0])); + CKERR(r); + // r = toku_pthread_create(toku_uninstrumented, &client_threads[1], 0, + // client, (void *)&client_specs[1]); CKERR(r); struct timeval start, now; - if ( verbose ) { + if (verbose) { printf("test_indexer build\n"); gettimeofday(&start,0); } @@ -342,14 +349,13 @@ static void test_indexer(DB *src, DB **dbs) if ( verbose ) printf("test_indexer done\n"); } - -static void run_test(void) -{ +static void run_test(void) { int r; - toku_mutex_init(&put_lock, NULL); + toku_mutex_init(toku_uninstrumented, &put_lock, nullptr); toku_os_recursive_delete(TOKU_TEST_FILENAME); - r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); - char logname[TOKU_PATH_MAX+1]; + r = toku_os_mkdir(TOKU_TEST_FILENAME, S_IRWXU + S_IRWXG + S_IRWXO); + CKERR(r); + char logname[TOKU_PATH_MAX + 1]; r = toku_os_mkdir(toku_path_join(logname, 2, TOKU_TEST_FILENAME, "log"), S_IRWXU+S_IRWXG+S_IRWXO); CKERR(r); r = db_env_create(&env, 0); CKERR(r); diff --git a/storage/tokudb/PerconaFT/src/tests/hotindexer-multiclient.cc b/storage/tokudb/PerconaFT/src/tests/hotindexer-multiclient.cc index eefc621f80a..004a19eccec 100644 --- a/storage/tokudb/PerconaFT/src/tests/hotindexer-multiclient.cc +++ b/storage/tokudb/PerconaFT/src/tests/hotindexer-multiclient.cc @@ -303,13 +303,25 @@ static void test_indexer(DB *src, DB **dbs) r = indexer->set_poll_function(indexer, poll_print, NULL); CKERR(r); - // start threads doing additional inserts - no lock issues since indexer already created - r = toku_pthread_create(&client_threads[0], 0, client, (void *)&client_specs[0]); CKERR(r); - r = toku_pthread_create(&client_threads[1], 0, client, (void *)&client_specs[1]); CKERR(r); -// r = toku_pthread_create(&client_threads[2], 0, client, (void *)&client_specs[2]); CKERR(r); + // start threads doing additional inserts - no lock issues since indexer + // already created + r = toku_pthread_create(toku_uninstrumented, + &client_threads[0], + nullptr, + client, + static_cast<void *>(&client_specs[0])); + CKERR(r); + r = toku_pthread_create(toku_uninstrumented, + &client_threads[1], + nullptr, + client, + static_cast<void *>(&client_specs[1])); + CKERR(r); + // r = toku_pthread_create(toku_uninstrumented, &client_threads[2], 0, + // client, (void *)&client_specs[2]); CKERR(r); struct timeval start, now; - if ( verbose ) { + if (verbose) { printf("test_indexer build\n"); gettimeofday(&start,0); } diff --git a/storage/tokudb/PerconaFT/src/tests/hotindexer-put-abort.cc b/storage/tokudb/PerconaFT/src/tests/hotindexer-put-abort.cc index 27501291b15..f4dd9c53ed5 100644 --- a/storage/tokudb/PerconaFT/src/tests/hotindexer-put-abort.cc +++ b/storage/tokudb/PerconaFT/src/tests/hotindexer-put-abort.cc @@ -142,11 +142,14 @@ run_test(void) { } // run the indexer - struct indexer_arg indexer_arg = { env, src_db, 1, &dest_db }; + struct indexer_arg indexer_arg = {env, src_db, 1, &dest_db}; toku_pthread_t pid; - r = toku_pthread_create(&pid, NULL, indexer_thread, &indexer_arg); assert_zero(r); + r = toku_pthread_create( + toku_uninstrumented, &pid, nullptr, indexer_thread, &indexer_arg); + assert_zero(r); - r = txn->abort(txn); assert_zero(r); + r = txn->abort(txn); + assert_zero(r); void *ret; r = toku_pthread_join(pid, &ret); assert_zero(r); diff --git a/storage/tokudb/PerconaFT/src/tests/hotindexer-put-commit.cc b/storage/tokudb/PerconaFT/src/tests/hotindexer-put-commit.cc index 59b40037125..99c9bf301cc 100644 --- a/storage/tokudb/PerconaFT/src/tests/hotindexer-put-commit.cc +++ b/storage/tokudb/PerconaFT/src/tests/hotindexer-put-commit.cc @@ -166,12 +166,16 @@ run_test(void) { } // run the indexer - struct indexer_arg indexer_arg = { env, src_db, 1, &dest_db }; + struct indexer_arg indexer_arg = {env, src_db, 1, &dest_db}; toku_pthread_t pid; - r = toku_pthread_create(&pid, NULL, indexer_thread, &indexer_arg); assert_zero(r); - - if (verbose) fprintf(stderr, "commit start\n"); - r = txn->commit(txn, 0); assert_zero(r); + r = toku_pthread_create( + toku_uninstrumented, &pid, nullptr, indexer_thread, &indexer_arg); + assert_zero(r); + + if (verbose) + fprintf(stderr, "commit start\n"); + r = txn->commit(txn, 0); + assert_zero(r); if (verbose) fprintf(stderr, "commit end\n"); void *ret; diff --git a/storage/tokudb/PerconaFT/src/tests/hotindexer-with-queries.cc b/storage/tokudb/PerconaFT/src/tests/hotindexer-with-queries.cc index a0be49c1617..2bc60142f3c 100644 --- a/storage/tokudb/PerconaFT/src/tests/hotindexer-with-queries.cc +++ b/storage/tokudb/PerconaFT/src/tests/hotindexer-with-queries.cc @@ -114,10 +114,12 @@ static void query_only(DB *src) client_init(); // start thread doing query - r = toku_pthread_create(client_thread, 0, client, (void *)src); + r = toku_pthread_create( + toku_uninstrumented, client_thread, nullptr, + client, static_cast<void *>(src)); CKERR(r); - r = toku_pthread_join(*client_thread, &t0); + r = toku_pthread_join(*client_thread, &t0); CKERR(r); client_cleanup(); @@ -150,10 +152,13 @@ static void test_indexer(DB *src, DB **dbs) CKERR(r); // start thread doing query - r = toku_pthread_create(client_thread, 0, client, (void *)src); CKERR(r); + r = toku_pthread_create( + toku_uninstrumented, client_thread, nullptr, + client, static_cast<void *>(src)); + CKERR(r); struct timeval start, now; - if ( verbose ) { + if (verbose) { printf("test_indexer build\n"); gettimeofday(&start,0); } diff --git a/storage/tokudb/PerconaFT/src/tests/locktree_escalation_stalls.cc b/storage/tokudb/PerconaFT/src/tests/locktree_escalation_stalls.cc index b4874472bcb..e6c1b18b2b6 100644 --- a/storage/tokudb/PerconaFT/src/tests/locktree_escalation_stalls.cc +++ b/storage/tokudb/PerconaFT/src/tests/locktree_escalation_stalls.cc @@ -191,17 +191,22 @@ static void run_test(uint64_t max_i, int n_small) { env, big_db, max_i, big_test, }; toku_pthread_t big_id; - r = toku_pthread_create(&big_id, NULL, test_f, &big_test_args); + r = toku_pthread_create( + toku_uninstrumented, &big_id, nullptr, test_f, &big_test_args); assert(r == 0); struct test_args small_test_args[n_small]; toku_pthread_t small_id[n_small]; for (int i = 0; i < n_small; i++) { - small_test_args[i] = { env, small_db, max_i, small_test }; - r = toku_pthread_create(&small_id[i], NULL, test_f, &small_test_args[i]); + small_test_args[i] = {env, small_db, max_i, small_test}; + r = toku_pthread_create(toku_uninstrumented, + &small_id[i], + nullptr, + test_f, + &small_test_args[i]); assert(r == 0); } - + void *big_ret; r = toku_pthread_join(big_id, &big_ret); assert(r == 0); diff --git a/storage/tokudb/PerconaFT/src/tests/recover-test_crash_in_flusher_thread.h b/storage/tokudb/PerconaFT/src/tests/recover-test_crash_in_flusher_thread.h index 0ed68207ed4..5c10d0cb712 100644 --- a/storage/tokudb/PerconaFT/src/tests/recover-test_crash_in_flusher_thread.h +++ b/storage/tokudb/PerconaFT/src/tests/recover-test_crash_in_flusher_thread.h @@ -70,13 +70,18 @@ static void *do_checkpoint_and_crash(void *arg) { static void flt_callback(int flt_state, void* extra) { cnt++; if (verbose) printf("flt_state!! %d\n", flt_state); - if (cnt > 0 && !starting_a_chkpt && flt_state == state_to_crash) { - starting_a_chkpt = true; - if (verbose) printf("flt_state %d\n", flt_state); - int r = toku_pthread_create(&checkpoint_tid, NULL, do_checkpoint_and_crash, extra); - assert(r==0); - usleep(2*1000*1000); - } + if (cnt > 0 && !starting_a_chkpt && flt_state == state_to_crash) { + starting_a_chkpt = true; + if (verbose) + printf("flt_state %d\n", flt_state); + int r = toku_pthread_create(toku_uninstrumented, + &checkpoint_tid, + nullptr, + do_checkpoint_and_crash, + extra); + assert(r == 0); + usleep(2 * 1000 * 1000); + } } diff --git a/storage/tokudb/PerconaFT/src/tests/recovery_stress.cc b/storage/tokudb/PerconaFT/src/tests/recovery_stress.cc index b1f5f98a90a..1646030cc85 100644 --- a/storage/tokudb/PerconaFT/src/tests/recovery_stress.cc +++ b/storage/tokudb/PerconaFT/src/tests/recovery_stress.cc @@ -515,19 +515,8 @@ static void run_test (int iter) { // if requesting crash, randomly do other non-committed acts, then "drop_dead" if (iter > 0) { - if (verbose) printf("dying\n"); -#if 0 - // separate thread will perform random acts on other dictionaries (not 0) - r = toku_pthread_create(&thread, 0, random_acts, (void *) dictionaries); - CKERR(r); - // this thead will scribble over dictionary 0 before crash to verify that - // post-checkpoint inserts are not in the database - DB* db = dictionaries[0].db; - if (iter & 1) - scribble(db, iter); - else - thin_out(db, iter); -#endif + if (verbose) + printf("dying\n"); uint32_t delay = myrandom(); delay &= 0xFFF; // select lower 12 bits, shifted up 8 for random number ... delay = delay << 8; // ... uniformly distributed between 0 and 1M ... diff --git a/storage/tokudb/PerconaFT/src/tests/stress_openclose.h b/storage/tokudb/PerconaFT/src/tests/stress_openclose.h index 3f10bfe8aeb..3a55ca4486f 100644 --- a/storage/tokudb/PerconaFT/src/tests/stress_openclose.h +++ b/storage/tokudb/PerconaFT/src/tests/stress_openclose.h @@ -245,19 +245,16 @@ stress_table(DB_ENV *env, DB **dbp, struct cli_args *cli_args) { // which they can choose a random db to either touch or query XMALLOC_N(num_buckets, buckets); for (int i = 0; i < num_buckets; i++) { - struct db_bucket bucket = { - .env = env, - .db = dbp[i], - .is_open = true - }; + struct db_bucket bucket = {.env = env, .db = dbp[i], .is_open = true}; buckets[i] = bucket; - toku_mutex_init(&buckets[i].mutex, NULL); + toku_mutex_init(toku_uninstrumented, &buckets[i].mutex, nullptr); } // run all of the query and update workers. they may randomly open // and close the dbs in each db_bucket to be some random dictionary, // so when they're done we'll have to clean up the mess so this // stress test can exit gracefully expecting db[i] = the ith db - //verbose_printf("stressing %d tables using %d update threads, %d query threads\n", + // verbose_printf("stressing %d tables using %d update threads, %d query + // threads\n", // num_buckets, update_threads, query_threads); verbose_printf("stressing %d tables using %d update threads\n", num_buckets, update_threads); diff --git a/storage/tokudb/PerconaFT/src/tests/test3039.cc b/storage/tokudb/PerconaFT/src/tests/test3039.cc index 54a2b3bf730..6c38fa13592 100644 --- a/storage/tokudb/PerconaFT/src/tests/test3039.cc +++ b/storage/tokudb/PerconaFT/src/tests/test3039.cc @@ -184,30 +184,36 @@ void do_threads (unsigned long long N, int do_nonlocal) { toku_pthread_t ths[2]; struct reader_thread_state rstates[2] = {{.elapsed_time = 0.0, .n_did_read = 0, - .n_to_read = (long long signed) N, - .do_local = 1, - .finish = 0}, + .n_to_read = (long long signed)N, + .do_local = 1, + .finish = 0}, {.elapsed_time = 0.0, .n_did_read = 0, .n_to_read = -1, - .do_local = 0, - .finish = 0}}; + .do_local = 0, + .finish = 0}}; int n_to_create = do_nonlocal ? 2 : 1; - for (int i=0; i<n_to_create; i++) { - int r = toku_pthread_create(&ths[i], 0, reader_thread, (void*)&rstates[i]); - CKERR(r); + for (int i = 0; i < n_to_create; i++) { + int r = toku_pthread_create(toku_uninstrumented, + &ths[i], + nullptr, + reader_thread, + static_cast<void *>(&rstates[i])); + CKERR(r); } - for (int i=0; i<n_to_create; i++) { - void *retval; - int r = toku_pthread_join(ths[i], &retval); - CKERR(r); - assert(retval==0); - if (verbose) { - printf("%9s thread time = %8.2fs on %9lld reads (%.3f us/read)\n", - (i==0 ? "local" : "nonlocal"), - rstates[i].elapsed_time, rstates[i].n_did_read, rstates[i].elapsed_time/rstates[i].n_did_read * 1e6); - } - rstates[1].finish = 1; + for (int i = 0; i < n_to_create; i++) { + void *retval; + int r = toku_pthread_join(ths[i], &retval); + CKERR(r); + assert(retval == 0); + if (verbose) { + printf("%9s thread time = %8.2fs on %9lld reads (%.3f us/read)\n", + (i == 0 ? "local" : "nonlocal"), + rstates[i].elapsed_time, + rstates[i].n_did_read, + rstates[i].elapsed_time / rstates[i].n_did_read * 1e6); + } + rstates[1].finish = 1; } if (verbose && do_nonlocal) { printf("total %9lld reads (%.3f us/read)\n", diff --git a/storage/tokudb/PerconaFT/src/tests/test_1672532.cc b/storage/tokudb/PerconaFT/src/tests/test_1672532.cc new file mode 100644 index 00000000000..721e7677824 --- /dev/null +++ b/storage/tokudb/PerconaFT/src/tests/test_1672532.cc @@ -0,0 +1,210 @@ +/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil -*- */ +// vim: ft=cpp:expandtab:ts=8:sw=4:softtabstop=4: +#ident "$Id$" +/*====== +This file is part of PerconaFT. + + +Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. + + PerconaFT is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License, version 2, + as published by the Free Software Foundation. + + PerconaFT 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 PerconaFT. If not, see <http://www.gnu.org/licenses/>. + +---------------------------------------- + + PerconaFT is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + PerconaFT 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with PerconaFT. If not, see <http://www.gnu.org/licenses/>. +======= */ + +#ident \ + "Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved." + +#include "test.h" +// to verify the DB_LOCKING_READ works to lock the read rows for snapshot +// isolaton. +// we create a db, then init a read transaction with repeatable-read isolation +// and +// locking read flag, then we start another transaction to grab the write lock. +// DB_LOCKING_READ is defined here to just make the before and after tests work +// (before +// test did not have DB_LOCKING_READ flag). +#if !defined(DB_LOCKING_READ) +#define DB_LOCKING_READ 0 +#endif +static int prelock_range(DBC *cursor, int left, int right) { + DBT key_left; + dbt_init(&key_left, &left, sizeof left); + DBT key_right; + dbt_init(&key_right, &right, sizeof right); + int r = cursor->c_set_bounds(cursor, &key_left, &key_right, true, 0); + return r; +} + +static void test_read_write_range(DB_ENV *env, + DB *db, + uint32_t iso_flags, + int expect_r) { + int r; + + DB_TXN *txn_a = NULL; + r = env->txn_begin(env, NULL, &txn_a, iso_flags); + assert_zero(r); + DB_TXN *txn_b = NULL; + r = env->txn_begin(env, NULL, &txn_b, iso_flags); + assert_zero(r); + + DBC *cursor_a = NULL; + r = db->cursor(db, txn_a, &cursor_a, DB_LOCKING_READ); + assert_zero(r); + DBC *cursor_b = NULL; + r = db->cursor(db, txn_b, &cursor_b, DB_RMW); + assert_zero(r); + + r = prelock_range(cursor_a, htonl(10), htonl(100)); + assert_zero(r); + r = prelock_range(cursor_b, htonl(50), htonl(200)); + assert(r == expect_r); + + r = cursor_a->c_close(cursor_a); + assert_zero(r); + r = cursor_b->c_close(cursor_b); + assert_zero(r); + + r = txn_a->commit(txn_a, 0); + assert_zero(r); + r = txn_b->commit(txn_b, 0); + assert_zero(r); +} + +static void test_read_write_point(DB_ENV *env, + DB *db, + uint32_t iso_flags, + int expect_r) { + int r; + + DB_TXN *txn1 = NULL; + r = env->txn_begin(env, NULL, &txn1, iso_flags); + assert_zero(r); + + DB_TXN *txn2 = NULL; + r = env->txn_begin(env, NULL, &txn2, iso_flags); + assert_zero(r); + + DBC *c1 = NULL; + r = db->cursor(db, txn1, &c1, DB_LOCKING_READ); + assert_zero(r); + + DBC *c2 = NULL; + r = db->cursor(db, txn2, &c2, DB_RMW); + assert_zero(r); + + int k = htonl(42); + DBT key; + dbt_init(&key, &k, sizeof k); + DBT val; + memset(&val, 0, sizeof val); + r = c1->c_get(c1, &key, &val, DB_SET); + assert_zero(r); + + r = c2->c_get(c2, &key, &val, DB_SET); + assert(r == expect_r); + + r = c1->c_close(c1); + assert_zero(r); + r = c2->c_close(c2); + assert_zero(r); + + r = txn1->commit(txn1, 0); + assert_zero(r); + r = txn2->commit(txn2, 0); + assert_zero(r); +} + +int test_main(int argc, char *const argv[]) { + int r; + + const char *env_dir = TOKU_TEST_FILENAME; + const char *db_filename = "lockingreadtest"; + + parse_args(argc, argv); + + char rm_cmd[strlen(env_dir) + strlen("rm -rf ") + 1]; + snprintf(rm_cmd, sizeof(rm_cmd), "rm -rf %s", env_dir); + r = system(rm_cmd); + assert_zero(r); + + r = toku_os_mkdir(env_dir, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); + assert_zero(r); + + DB_ENV *env = NULL; + r = db_env_create(&env, 0); + assert_zero(r); + int env_open_flags = DB_CREATE | DB_PRIVATE | DB_INIT_MPOOL | DB_INIT_TXN | + DB_INIT_LOCK | DB_INIT_LOG; + r = env->open( + env, env_dir, env_open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + assert_zero(r); + + // create the db + DB *db = NULL; + r = db_create(&db, env, 0); + assert_zero(r); + DB_TXN *create_txn = NULL; + r = env->txn_begin(env, NULL, &create_txn, 0); + assert_zero(r); + r = db->open(db, + create_txn, + db_filename, + NULL, + DB_BTREE, + DB_CREATE, + S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); + assert_zero(r); + r = create_txn->commit(create_txn, 0); + assert_zero(r); + + // add a record + + DB_TXN *write_txn = NULL; + r = env->txn_begin(env, NULL, &write_txn, 0); + assert_zero(r); + + int k = htonl(42); + int v = 42; + DBT key; + dbt_init(&key, &k, sizeof k); + DBT val; + dbt_init(&val, &v, sizeof v); + r = db->put(db, write_txn, &key, &val, DB_NOOVERWRITE); + assert_zero(r); + r = write_txn->commit(write_txn, 0); + assert_zero(r); + + test_read_write_range(env, db, DB_TXN_SNAPSHOT, DB_LOCK_NOTGRANTED); + test_read_write_point(env, db, DB_TXN_SNAPSHOT, DB_LOCK_NOTGRANTED); + + r = db->close(db, 0); + assert_zero(r); + + r = env->close(env, 0); + assert_zero(r); + return 0; +} diff --git a/storage/tokudb/PerconaFT/src/tests/test_3645.cc b/storage/tokudb/PerconaFT/src/tests/test_3645.cc index bb5566b032d..e1fa37bef54 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_3645.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_3645.cc @@ -239,33 +239,61 @@ test_evictions (void) { // make the forward fast scanner myargs[0].fast = true; myargs[0].fwd = true; - { int chk_r = toku_pthread_create(&mytids[0], NULL, scan_db, &myargs[0]); CKERR(chk_r); } + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &mytids[0], nullptr, scan_db, &myargs[0]); + CKERR(chk_r); + } // make the forward slow scanner myargs[1].fast = false; myargs[1].fwd = true; - { int chk_r = toku_pthread_create(&mytids[1], NULL, scan_db, &myargs[1]); CKERR(chk_r); } + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &mytids[1], nullptr, scan_db, &myargs[1]); + CKERR(chk_r); + } // make the backward fast scanner myargs[2].fast = true; myargs[2].fwd = false; - { int chk_r = toku_pthread_create(&mytids[2], NULL, scan_db, &myargs[2]); CKERR(chk_r); } + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &mytids[2], nullptr, scan_db, &myargs[2]); + CKERR(chk_r); + } // make the backward slow scanner myargs[3].fast = false; myargs[3].fwd = false; - { int chk_r = toku_pthread_create(&mytids[3], NULL, scan_db, &myargs[3]); CKERR(chk_r); } + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &mytids[3], nullptr, scan_db, &myargs[3]); + CKERR(chk_r); + } // make the guy that updates the db - { int chk_r = toku_pthread_create(&mytids[4], NULL, update_db, &myargs[4]); CKERR(chk_r); } + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &mytids[4], nullptr, update_db, &myargs[4]); + CKERR(chk_r); + } // make the guy that does point queries - { int chk_r = toku_pthread_create(&mytids[5], NULL, ptquery_db, &myargs[5]); CKERR(chk_r); } + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &mytids[5], nullptr, ptquery_db, &myargs[5]); + CKERR(chk_r); + } // make the guy that sleeps - { int chk_r = toku_pthread_create(&mytids[6], NULL, test_time, NULL); CKERR(chk_r); } - - for (uint32_t i = 0; i < sizeof(myargs)/sizeof(myargs[0]); i++) { + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &mytids[6], nullptr, test_time, nullptr); + CKERR(chk_r); + } + + for (uint32_t i = 0; i < sizeof(myargs) / sizeof(myargs[0]); i++) { void *ret; r = toku_pthread_join(mytids[i], &ret); assert_zero(r); } diff --git a/storage/tokudb/PerconaFT/src/tests/test_4015.cc b/storage/tokudb/PerconaFT/src/tests/test_4015.cc index dc18242b489..1231e3b4bca 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_4015.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_4015.cc @@ -151,10 +151,18 @@ int test_main(int argc, char * const argv[]) { { int chk_r = db->open(db, NULL, "db", NULL, DB_BTREE, DB_CREATE, 0666); CKERR(chk_r); } DBT desc; dbt_init(&desc, "foo", sizeof("foo")); - IN_TXN_COMMIT(env, NULL, txn, 0, - { int chk_r = db->change_descriptor(db, txn, &desc, DB_UPDATE_CMP_DESCRIPTOR); CKERR(chk_r); }); + IN_TXN_COMMIT(env, NULL, txn, 0, { + int chk_r = + db->change_descriptor(db, txn, &desc, DB_UPDATE_CMP_DESCRIPTOR); + CKERR(chk_r); + }); pthread_t thd; - { int chk_r = toku_pthread_create(&thd, NULL, startA, NULL); CKERR(chk_r); } + { + int chk_r = + toku_pthread_create( + toku_uninstrumented, &thd, nullptr, startA, nullptr); + CKERR(chk_r); + } startB(); diff --git a/storage/tokudb/PerconaFT/src/tests/test_abort1.cc b/storage/tokudb/PerconaFT/src/tests/test_abort1.cc index 55449610ffb..7b60364878b 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_abort1.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_abort1.cc @@ -87,10 +87,12 @@ test_db_open_aborts (void) { CKERR2(r, DB_NOTFOUND); } toku_struct_stat statbuf; - char filename[TOKU_PATH_MAX+1]; - r = toku_stat(toku_path_join(filename, 2, TOKU_TEST_FILENAME, "foo.db"), &statbuf); - assert(r!=0); - assert(errno==ENOENT); + char filename[TOKU_PATH_MAX + 1]; + r = toku_stat(toku_path_join(filename, 2, TOKU_TEST_FILENAME, "foo.db"), + &statbuf, + toku_uninstrumented); + assert(r != 0); + assert(errno == ENOENT); } r=env->close(env, 0); assert(r==0); @@ -153,10 +155,12 @@ test_db_put_aborts (void) { CAST_FROM_VOIDP(filename, iname.data); assert(filename); } - toku_struct_stat statbuf; - char fullfile[TOKU_PATH_MAX+1]; - r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), &statbuf); - assert(r==0); + toku_struct_stat statbuf; + char fullfile[TOKU_PATH_MAX + 1]; + r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), + &statbuf, + toku_uninstrumented); + assert(r == 0); toku_free(filename); } // But the item should not be in it. diff --git a/storage/tokudb/PerconaFT/src/tests/test_abort4.cc b/storage/tokudb/PerconaFT/src/tests/test_abort4.cc index e67efb465b2..e797fc640d8 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_abort4.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_abort4.cc @@ -160,10 +160,12 @@ verify_and_tear_down(int close_first) { CAST_FROM_VOIDP(filename, iname.data); assert(filename); } - toku_struct_stat statbuf; - char fullfile[TOKU_PATH_MAX+1]; - r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), &statbuf); - assert(r==0); + toku_struct_stat statbuf; + char fullfile[TOKU_PATH_MAX + 1]; + r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), + &statbuf, + toku_uninstrumented); + assert(r == 0); toku_free(filename); } CKERR(r); diff --git a/storage/tokudb/PerconaFT/src/tests/test_abort5.cc b/storage/tokudb/PerconaFT/src/tests/test_abort5.cc index 728afcce1b9..d5d056d5126 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_abort5.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_abort5.cc @@ -191,10 +191,12 @@ verify_and_tear_down(int close_first) { CAST_FROM_VOIDP(filename, iname.data); assert(filename); } - toku_struct_stat statbuf; - char fullfile[TOKU_PATH_MAX+1]; - r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), &statbuf); - assert(r==0); + toku_struct_stat statbuf; + char fullfile[TOKU_PATH_MAX + 1]; + r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), + &statbuf, + toku_uninstrumented); + assert(r == 0); toku_free(filename); } if (close_first) { diff --git a/storage/tokudb/PerconaFT/src/tests/test_forkjoin.cc b/storage/tokudb/PerconaFT/src/tests/test_forkjoin.cc index 910cf46e513..766372a15c2 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_forkjoin.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_forkjoin.cc @@ -48,12 +48,13 @@ f (void *arg) { return arg; } -int -test_main(int argc, char *const argv[]) { +int test_main(int argc, char *const argv[]) { parse_args(argc, argv); toku_pthread_t t; - int r = toku_pthread_create(&t, 0, f, 0); assert(r == 0); + int r = toku_pthread_create(toku_uninstrumented, &t, nullptr, f, nullptr); + assert(r == 0); void *ret; - r = toku_pthread_join(t, &ret); assert(r == 0); + r = toku_pthread_join(t, &ret); + assert(r == 0); return 0; } diff --git a/storage/tokudb/PerconaFT/src/tests/test_groupcommit_count.cc b/storage/tokudb/PerconaFT/src/tests/test_groupcommit_count.cc index 414ddd2b70a..35104c2a569 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_groupcommit_count.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_groupcommit_count.cc @@ -87,12 +87,16 @@ test_groupcommit (int nthreads) { int i; toku_pthread_t threads[nthreads]; int whichthread[nthreads]; - for (i=0; i<nthreads; i++) { - whichthread[i]=i; - r=toku_pthread_create(&threads[i], 0, start_a_thread, &whichthread[i]); + for (i = 0; i < nthreads; i++) { + whichthread[i] = i; + r = toku_pthread_create(toku_uninstrumented, + &threads[i], + nullptr, + start_a_thread, + &whichthread[i]); } - for (i=0; i<nthreads; i++) { - toku_pthread_join(threads[i], 0); + for (i = 0; i < nthreads; i++) { + toku_pthread_join(threads[i], 0); } r=db->close(db, 0); assert(r==0); diff --git a/storage/tokudb/PerconaFT/src/tests/test_groupcommit_perf.cc b/storage/tokudb/PerconaFT/src/tests/test_groupcommit_perf.cc index 94eaf2a01a9..6f872d10a32 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_groupcommit_perf.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_groupcommit_perf.cc @@ -84,12 +84,16 @@ test_groupcommit (int nthreads) { int i; toku_pthread_t threads[nthreads]; int whichthread[nthreads]; - for (i=0; i<nthreads; i++) { - whichthread[i]=i; - r=toku_pthread_create(&threads[i], 0, start_a_thread, &whichthread[i]); + for (i = 0; i < nthreads; i++) { + whichthread[i] = i; + r = toku_pthread_create(toku_uninstrumented, + &threads[i], + nullptr, + start_a_thread, + &whichthread[i]); } - for (i=0; i<nthreads; i++) { - toku_pthread_join(threads[i], 0); + for (i = 0; i < nthreads; i++) { + toku_pthread_join(threads[i], 0); } #if 0 r=env->txn_begin(env, 0, &tid, 0); CKERR(r); diff --git a/storage/tokudb/PerconaFT/src/tests/test_iterate_pending_lock_requests.cc b/storage/tokudb/PerconaFT/src/tests/test_iterate_pending_lock_requests.cc index f2bf0a2c756..66471a74af2 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_iterate_pending_lock_requests.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_iterate_pending_lock_requests.cc @@ -112,12 +112,17 @@ int test_main(int UU(argc), char *const UU(argv[])) { acquire_lock(txn1, magic_key); acquire_lock_extra e1(txn2, magic_key); - r = toku_pthread_create(&thread1, NULL, acquire_lock_thread, &e1); CKERR(r); + r = toku_pthread_create( + toku_uninstrumented, &thread1, nullptr, acquire_lock_thread, &e1); + CKERR(r); acquire_lock_extra e2(txn3, magic_key); - r = toku_pthread_create(&thread2, NULL, acquire_lock_thread, &e2); CKERR(r); + r = toku_pthread_create( + toku_uninstrumented, &thread2, nullptr, acquire_lock_thread, &e2); + CKERR(r); sleep(1); - r = env->iterate_pending_lock_requests(env, iterate_callback, NULL); CKERR(r); + r = env->iterate_pending_lock_requests(env, iterate_callback, NULL); + CKERR(r); invariant(iterate_callback_called == 2); void *v; diff --git a/storage/tokudb/PerconaFT/src/tests/test_lock_timeout_callback.cc b/storage/tokudb/PerconaFT/src/tests/test_lock_timeout_callback.cc index 75ea49ec858..571bae69916 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_lock_timeout_callback.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_lock_timeout_callback.cc @@ -118,7 +118,8 @@ int test_main(int UU(argc), char *const UU(argv[])) { acquire_lock(txn2, magic_key + 1); toku_pthread_t thread; acquire_lock_extra e(txn1, magic_key + 1); - r = toku_pthread_create(&thread, NULL, acquire_lock_thread, &e); + r = toku_pthread_create( + toku_uninstrumented, &thread, nullptr, acquire_lock_thread, &e); usleep(100000); acquire_lock(txn2, magic_key); invariant(callback_calls == 2); diff --git a/storage/tokudb/PerconaFT/src/tests/test_log1.cc b/storage/tokudb/PerconaFT/src/tests/test_log1.cc index 65fa1d830ef..5473a8e3d5e 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_log1.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_log1.cc @@ -87,10 +87,12 @@ static void make_db (bool close_env) { r=tid->commit(tid, 0); assert(r==0); r=db->close(db, 0); assert(r==0); { - toku_struct_stat statbuf; - char fullfile[TOKU_PATH_MAX+1]; - r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), &statbuf); - assert(r==0); + toku_struct_stat statbuf; + char fullfile[TOKU_PATH_MAX + 1]; + r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), + &statbuf, + toku_uninstrumented); + assert(r == 0); toku_free(filename); } if (close_env) { diff --git a/storage/tokudb/PerconaFT/src/tests/test_log1_abort.cc b/storage/tokudb/PerconaFT/src/tests/test_log1_abort.cc index 92c3657a154..c66409fb823 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_log1_abort.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_log1_abort.cc @@ -80,11 +80,13 @@ test_main (int UU(argc), char UU(*const argv[])) { r=env->close(env, 0); assert(r==0); { - toku_struct_stat statbuf; - char filename[TOKU_PATH_MAX+1]; - r = toku_stat(toku_path_join(filename, 2, TOKU_TEST_FILENAME, "foo.db"), &statbuf); - assert(r==-1); - assert(errno==ENOENT); + toku_struct_stat statbuf; + char filename[TOKU_PATH_MAX + 1]; + r = toku_stat(toku_path_join(filename, 2, TOKU_TEST_FILENAME, "foo.db"), + &statbuf, + toku_uninstrumented); + assert(r == -1); + assert(errno == ENOENT); } return 0; } diff --git a/storage/tokudb/PerconaFT/src/tests/test_logmax.cc b/storage/tokudb/PerconaFT/src/tests/test_logmax.cc index e5de0a5d906..133eb36ddb5 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_logmax.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_logmax.cc @@ -50,14 +50,19 @@ check_logmax (int max) { struct dirent *ent; while ((ent=readdir(dir))) { if ((ent->d_type==DT_REG || ent->d_type==DT_UNKNOWN) && strncmp(ent->d_name, "log", 3)==0) { - // It is a "log*" file - char full_fname[TOKU_PATH_MAX+1]; - toku_struct_stat sbuf; - int r = toku_stat(toku_path_join(full_fname, 2, TOKU_TEST_FILENAME, ent->d_name), &sbuf); - assert(r==0); - if (verbose) - printf("%s is of size %" PRId64 "\n", ent->d_name, (int64_t)sbuf.st_size); - if (sbuf.st_size > max) any_too_big=1; + // It is a "log*" file + char full_fname[TOKU_PATH_MAX + 1]; + toku_struct_stat sbuf; + int r = toku_stat( + toku_path_join(full_fname, 2, TOKU_TEST_FILENAME, ent->d_name), + &sbuf, + toku_uninstrumented); + assert(r == 0); + if (verbose) + printf("%s is of size %" PRId64 "\n", + ent->d_name, + (int64_t)sbuf.st_size); + if (sbuf.st_size > max) any_too_big=1; } } assert(!any_too_big); diff --git a/storage/tokudb/PerconaFT/src/tests/test_multiple_checkpoints_block_commit.cc b/storage/tokudb/PerconaFT/src/tests/test_multiple_checkpoints_block_commit.cc index 66e9f4a5ec8..da53a7bfe11 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_multiple_checkpoints_block_commit.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_multiple_checkpoints_block_commit.cc @@ -101,10 +101,17 @@ static void run_test(void) { toku_pthread_t chkpt1_tid; toku_pthread_t chkpt2_tid; - - { int chk_r = toku_pthread_create(&chkpt1_tid, NULL, run_checkpoint, NULL); CKERR(chk_r); } - { int chk_r = toku_pthread_create(&chkpt2_tid, NULL, run_checkpoint, NULL); CKERR(chk_r); } - usleep(2*1024*1024); + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &chkpt1_tid, nullptr, run_checkpoint, nullptr); + CKERR(chk_r); + } + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &chkpt2_tid, nullptr, run_checkpoint, nullptr); + CKERR(chk_r); + } + usleep(2 * 1024 * 1024); struct timeval tstart; gettimeofday(&tstart, NULL); DB_TXN *txn = NULL; diff --git a/storage/tokudb/PerconaFT/src/tests/test_stress_hot_indexing.cc b/storage/tokudb/PerconaFT/src/tests/test_stress_hot_indexing.cc index e0bf0d2ec6f..6395f591660 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_stress_hot_indexing.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_stress_hot_indexing.cc @@ -312,12 +312,11 @@ stress_table(DB_ENV *env, DB **dbp, struct cli_args *cli_args) { run_workers(myargs, num_threads, cli_args->num_seconds, false, cli_args); } -int -test_main(int argc, char *const argv[]) { +int test_main(int argc, char *const argv[]) { gid_count = 0; memset(hi_gid, 0, sizeof(hi_gid)); - toku_mutex_init(&hi_lock, NULL); - toku_mutex_init(&fops_lock, NULL); + toku_mutex_init(toku_uninstrumented, &hi_lock, nullptr); + toku_mutex_init(toku_uninstrumented, &fops_lock, nullptr); hot_db = NULL; struct cli_args args = get_default_args(); // let's make default checkpointing period really slow diff --git a/storage/tokudb/PerconaFT/src/tests/test_thread_insert.cc b/storage/tokudb/PerconaFT/src/tests/test_thread_insert.cc index 0d5245e8f80..a266de638f1 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_thread_insert.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_thread_insert.cc @@ -150,10 +150,13 @@ test_main(int argc, char *const argv[]) { work[i].endno = n; } - if (verbose) printf("pid:%d\n", toku_os_getpid()); + if (verbose) + printf("pid:%d\n", toku_os_getpid()); - for (i=1; i<nthreads; i++) { - r = toku_pthread_create(&work[i].tid, 0, do_inserts, &work[i]); assert(r == 0); + for (i = 1; i < nthreads; i++) { + r = toku_pthread_create( + toku_uninstrumented, &work[i].tid, nullptr, do_inserts, &work[i]); + assert(r == 0); } work[0].do_exit = 0; diff --git a/storage/tokudb/PerconaFT/src/tests/test_txn_abort7.cc b/storage/tokudb/PerconaFT/src/tests/test_txn_abort7.cc index fb428f437b1..0a4463644b3 100644 --- a/storage/tokudb/PerconaFT/src/tests/test_txn_abort7.cc +++ b/storage/tokudb/PerconaFT/src/tests/test_txn_abort7.cc @@ -79,10 +79,12 @@ test_abort_create (void) { CAST_FROM_VOIDP(filename, iname.data); assert(filename); } - toku_struct_stat statbuf; - char fullfile[TOKU_PATH_MAX+1]; - r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), &statbuf); - assert(r==0); + toku_struct_stat statbuf; + char fullfile[TOKU_PATH_MAX + 1]; + r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, filename), + &statbuf, + toku_uninstrumented); + assert(r == 0); toku_free(filename); } @@ -100,10 +102,13 @@ test_abort_create (void) { CKERR2(r, DB_NOTFOUND); } toku_struct_stat statbuf; - char fullfile[TOKU_PATH_MAX+1]; - r = toku_stat(toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, "test.db"), &statbuf); - assert(r!=0); - assert(errno==ENOENT); + char fullfile[TOKU_PATH_MAX + 1]; + r = toku_stat( + toku_path_join(fullfile, 2, TOKU_TEST_FILENAME, "test.db"), + &statbuf, + toku_uninstrumented); + assert(r != 0); + assert(errno == ENOENT); } r = env->close(env, 0); assert(r == 0); diff --git a/storage/tokudb/PerconaFT/src/tests/threaded_stress_test_helpers.h b/storage/tokudb/PerconaFT/src/tests/threaded_stress_test_helpers.h index f2bacceed9d..e232f327d10 100644 --- a/storage/tokudb/PerconaFT/src/tests/threaded_stress_test_helpers.h +++ b/storage/tokudb/PerconaFT/src/tests/threaded_stress_test_helpers.h @@ -469,11 +469,11 @@ static int get_commit_flags(struct cli_args *args) { } struct worker_extra { - struct arg* thread_arg; + struct arg *thread_arg; toku_mutex_t *operation_lock_mutex; - struct rwlock *operation_lock; + struct st_rwlock *operation_lock; uint64_t *counters; - int64_t pad[4]; // pad to 64 bytes + int64_t pad[4]; // pad to 64 bytes }; static void lock_worker_op(struct worker_extra* we) { @@ -1772,11 +1772,12 @@ static int run_workers( ) { int r; - const struct perf_formatter *perf_formatter = &perf_formatters[cli_args->perf_output_format]; + const struct perf_formatter *perf_formatter = + &perf_formatters[cli_args->perf_output_format]; toku_mutex_t mutex = ZERO_MUTEX_INITIALIZER; - toku_mutex_init(&mutex, nullptr); - struct rwlock rwlock; - rwlock_init(&rwlock); + toku_mutex_init(toku_uninstrumented, &mutex, nullptr); + struct st_rwlock rwlock; + rwlock_init(toku_uninstrumented, &rwlock); toku_pthread_t tids[num_threads]; toku_pthread_t time_tid; if (cli_args->print_performance) { @@ -1798,15 +1799,26 @@ static int run_workers( worker_extra[i].thread_arg = &thread_args[i]; worker_extra[i].operation_lock = &rwlock; worker_extra[i].operation_lock_mutex = &mutex; - XCALLOC_N((int) NUM_OPERATION_TYPES, worker_extra[i].counters); + XCALLOC_N((int)NUM_OPERATION_TYPES, worker_extra[i].counters); TOKU_DRD_IGNORE_VAR(worker_extra[i].counters); - { int chk_r = toku_pthread_create(&tids[i], nullptr, worker, &worker_extra[i]); CKERR(chk_r); } + { + int chk_r = toku_pthread_create(toku_uninstrumented, + &tids[i], + nullptr, + worker, + &worker_extra[i]); + CKERR(chk_r); + } if (verbose) - printf("%lu created\n", (unsigned long) tids[i]); + printf("%lu created\n", (unsigned long)tids[i]); + } + { + int chk_r = toku_pthread_create( + toku_uninstrumented, &time_tid, nullptr, test_time, &tte); + CKERR(chk_r); } - { int chk_r = toku_pthread_create(&time_tid, nullptr, test_time, &tte); CKERR(chk_r); } if (verbose) - printf("%lu created\n", (unsigned long) time_tid); + printf("%lu created\n", (unsigned long)time_tid); void *ret; r = toku_pthread_join(time_tid, &ret); assert_zero(r); @@ -1817,17 +1829,22 @@ static int run_workers( // threads (i.e. there is some runaway thread). struct sleep_and_crash_extra sac_extra; ZERO_STRUCT(sac_extra); - toku_mutex_init(&sac_extra.mutex, nullptr); - toku_cond_init(&sac_extra.cond, nullptr); + toku_mutex_init(toku_uninstrumented, &sac_extra.mutex, nullptr); + toku_cond_init(toku_uninstrumented, &sac_extra.cond, nullptr); sac_extra.seconds = cli_args->join_timeout; sac_extra.is_setup = false; sac_extra.threads_have_joined = false; toku_mutex_lock(&sac_extra.mutex); toku_pthread_t sac_thread; - r = toku_pthread_create(&sac_thread, nullptr, sleep_and_crash, &sac_extra); + r = toku_pthread_create(toku_uninstrumented, + &sac_thread, + nullptr, + sleep_and_crash, + &sac_extra); assert_zero(r); - // Wait for sleep_and_crash thread to get set up, spinning is ok, this should be quick. + // Wait for sleep_and_crash thread to get set up, spinning is ok, this + // should be quick. while (!sac_extra.is_setup) { toku_mutex_unlock(&sac_extra.mutex); r = toku_pthread_yield(); diff --git a/storage/tokudb/PerconaFT/src/tests/txn_manager_handle_snapshot_atomicity.cc b/storage/tokudb/PerconaFT/src/tests/txn_manager_handle_snapshot_atomicity.cc index 30cc16d73a7..469e78f492f 100644 --- a/storage/tokudb/PerconaFT/src/tests/txn_manager_handle_snapshot_atomicity.cc +++ b/storage/tokudb/PerconaFT/src/tests/txn_manager_handle_snapshot_atomicity.cc @@ -52,8 +52,8 @@ struct test_sync { static void test_sync_init(struct test_sync *UU(sync)) { #if TOKU_DEBUG_TXN_SYNC sync->state = 0; - toku_mutex_init(&sync->lock, NULL); - toku_cond_init(&sync->cv, NULL); + toku_mutex_init(toku_uninstrumented, &sync->lock, nullptr); + toku_cond_init(toku_uninstrumented, &sync->cv, nullptr); #endif } diff --git a/storage/tokudb/PerconaFT/src/ydb.cc b/storage/tokudb/PerconaFT/src/ydb.cc index 886832cec6a..9875e9227d4 100644 --- a/storage/tokudb/PerconaFT/src/ydb.cc +++ b/storage/tokudb/PerconaFT/src/ydb.cc @@ -228,7 +228,7 @@ env_fs_poller(void *arg) { int in_red; // set true to prevent certain operations (returning ENOSPC) // get the fs sizes for the home dir - uint64_t avail_size, total_size; + uint64_t avail_size = 0, total_size = 0; r = toku_get_filesystem_sizes(env->i->dir, &avail_size, NULL, &total_size); assert(r == 0); in_yellow = (avail_size < 2 * env_fs_redzone(env, total_size)); @@ -644,7 +644,7 @@ static int validate_env(DB_ENV *env, path = toku_construct_full_name( 2, env->i->dir, toku_product_name_strings.environmentdictionary); assert(path); - r = toku_stat(path, &buf); + r = toku_stat(path, &buf, toku_uninstrumented); if (r == 0) { expect_newenv = false; // persistent info exists } else { @@ -669,7 +669,7 @@ static int validate_env(DB_ENV *env, path = toku_construct_full_name( 2, env->i->dir, toku_product_name_strings.rollback_cachefile); assert(path); - r = toku_stat(path, &buf); + r = toku_stat(path, &buf, toku_uninstrumented); if (r == 0) { if (expect_newenv) // rollback cachefile exists, but persistent env // is missing @@ -711,7 +711,7 @@ static int validate_env(DB_ENV *env, path = toku_construct_full_name( 2, env->i->dir, toku_product_name_strings.fileopsdirectory); assert(path); - r = toku_stat(path, &buf); + r = toku_stat(path, &buf, toku_uninstrumented); if (r == 0) { if (expect_newenv) // fileops directory exists, but persistent env // is missing @@ -857,10 +857,11 @@ env_open(DB_ENV * env, const char *home, uint32_t flags, int mode) { // Verify that the home exists. toku_struct_stat buf; - r = toku_stat(home, &buf); + r = toku_stat(home, &buf, toku_uninstrumented); if (r != 0) { int e = get_error_errno(); - r = toku_ydb_do_error(env, e, "Error from toku_stat(\"%s\",...)\n", home); + r = toku_ydb_do_error( + env, e, "Error from toku_stat(\"%s\",...)\n", home); goto cleanup; } unused_flags &= ~DB_PRIVATE; @@ -876,13 +877,22 @@ env_open(DB_ENV * env, const char *home, uint32_t flags, int mode) { env->i->open_flags = flags; env->i->open_mode = mode; + // Instrumentation probe start + TOKU_PROBE_START(toku_instr_probe_1); + env_setup_real_data_dir(env); env_setup_real_log_dir(env); env_setup_real_tmp_dir(env); - r = toku_single_process_lock(env->i->dir, "environment", &env->i->envdir_lockfd); - if (r!=0) goto cleanup; - r = toku_single_process_lock(env->i->real_data_dir, "data", &env->i->datadir_lockfd); + // Instrumentation probe stop + toku_instr_probe_1->stop(); + + r = toku_single_process_lock( + env->i->dir, "environment", &env->i->envdir_lockfd); + if (r != 0) + goto cleanup; + r = toku_single_process_lock( + env->i->real_data_dir, "data", &env->i->datadir_lockfd); if (r!=0) goto cleanup; r = toku_single_process_lock(env->i->real_log_dir, "logs", &env->i->logdir_lockfd); if (r!=0) goto cleanup; @@ -2932,7 +2942,8 @@ toku_env_create(DB_ENV ** envp, uint32_t flags) { result->i->open_dbs_by_dname->create(); XMALLOC(result->i->open_dbs_by_dict_id); result->i->open_dbs_by_dict_id->create(); - toku_pthread_rwlock_init(&result->i->open_dbs_rwlock, NULL); + toku_pthread_rwlock_init( + *result_i_open_dbs_rwlock_key, &result->i->open_dbs_rwlock, nullptr); *envp = result; r = 0; diff --git a/storage/tokudb/PerconaFT/src/ydb_db.cc b/storage/tokudb/PerconaFT/src/ydb_db.cc index 29d21ad0452..6b4452325f4 100644 --- a/storage/tokudb/PerconaFT/src/ydb_db.cc +++ b/storage/tokudb/PerconaFT/src/ydb_db.cc @@ -84,53 +84,56 @@ ydb_db_layer_get_status(YDB_DB_LAYER_STATUS statp) { *statp = ydb_db_layer_status; } -void create_iname_hint(const char *dname, char *hint) { +void create_iname_hint(DB_ENV *env, const char *dname, char *hint) { //Requires: size of hint array must be > strlen(dname) //Copy alphanumeric characters only. //Replace strings of non-alphanumeric characters with a single underscore. - bool underscored = false; - while (*dname) { - if (isalnum(*dname)) { - char c = *dname++; - *hint++ = c; - underscored = false; - } - else { - if (!underscored) - *hint++ = '_'; - dname++; - underscored = true; + if (env->get_dir_per_db(env) && !toku_os_is_absolute_name(dname)) { + assert(dname); + if (*dname == '.') + ++dname; + if (*dname == '/') + ++dname; + bool underscored = false; + bool dbdir_is_parsed = false; + // Do not change the first '/' because this is + // delimiter which splits name into database dir + // and table dir. + while (*dname) { + if (isalnum(*dname) || (*dname == '/' && !dbdir_is_parsed)) { + char c = *dname++; + *hint++ = c; + if (c == '/') + dbdir_is_parsed = true; + underscored = false; + } else if (!dbdir_is_parsed) { + char c = *dname++; + *hint++ = c; + } else { + if (!underscored) + *hint++ = '_'; + dname++; + underscored = true; + } } - } - *hint = '\0'; -} - -void create_iname_hint_for_dbdir(const char *dname, char *hint) { - assert(dname); - if (*dname == '.') - ++dname; - if (*dname == '/') - ++dname; - bool underscored = false; - bool dbdir_is_parsed = false; - // Do not change the first '/' because this is - // delimiter which splits name into database dir - // and table dir. - while (*dname) { - if (isalnum(*dname) || (*dname == '/' && !dbdir_is_parsed)) { - char c = *dname++; - *hint++ = c; - if (c == '/') - dbdir_is_parsed = true; - underscored = false; - } else { - if (!underscored) - *hint++ = '_'; - dname++; - underscored = true; + *hint = '\0'; + } else { + bool underscored = false; + while (*dname) { + if (isalnum(*dname)) { + char c = *dname++; + *hint++ = c; + underscored = false; + } + else { + if (!underscored) + *hint++ = '_'; + dname++; + underscored = true; + } } + *hint = '\0'; } - *hint = '\0'; } // n < 0 means to ignore mark and ignore n @@ -188,10 +191,7 @@ std::unique_ptr<char[], decltype(&toku_free)> generate_iname_for_rename_or_open( } else if (is_open) id1 = toku_sync_fetch_and_add(&nontransactional_open_id, 1); - if (env->get_dir_per_db(env) && !toku_os_is_absolute_name(dname)) - create_iname_hint_for_dbdir(dname, hint); - else - create_iname_hint(dname, hint); + create_iname_hint(env, dname, hint); result.reset(create_iname(env, id1, id2, hint, NULL, -1)); @@ -1222,15 +1222,18 @@ load_inames(DB_ENV * env, DB_TXN * txn, int N, DB * dbs[/*N*/], const char * new for (i = 0; i < N; i++) { char * dname = dbs[i]->i->dname; toku_fill_dbt(&dname_dbt, dname, strlen(dname)+1); + // now create new iname char hint[strlen(dname) + 1]; - if (env->get_dir_per_db(env) && !toku_os_is_absolute_name(dname)) - create_iname_hint_for_dbdir(dname, hint); - else - create_iname_hint(dname, hint); - const char *new_iname = create_iname(env, xid.parent_id64, xid.child_id64, hint, mark, i); // allocates memory for iname_in_env + create_iname_hint(env, dname, hint); + + // allocates memory for iname_in_env + const char *new_iname = + create_iname(env, xid.parent_id64, xid.child_id64, hint, mark, i); new_inames_in_env[i] = new_iname; - toku_fill_dbt(&iname_dbt, new_iname, strlen(new_iname) + 1); // iname_in_env goes in directory + + // iname_in_env goes in directory + toku_fill_dbt(&iname_dbt, new_iname, strlen(new_iname) + 1); rval = toku_db_put(env->i->directory, txn, &dname_dbt, &iname_dbt, 0, true); if (rval) break; } diff --git a/storage/tokudb/PerconaFT/src/ydb_db.h b/storage/tokudb/PerconaFT/src/ydb_db.h index 8be28857c14..ab8fcd2a401 100644 --- a/storage/tokudb/PerconaFT/src/ydb_db.h +++ b/storage/tokudb/PerconaFT/src/ydb_db.h @@ -122,8 +122,7 @@ toku_db_destruct_autotxn(DB_TXN *txn, int r, bool changed) { return r; } -void create_iname_hint_for_dbdir(const char *dname, char *hint); -void create_iname_hint(const char *dname, char *hint); +void create_iname_hint(DB_ENV *env, const char *dname, char *hint); char *create_iname(DB_ENV *env, uint64_t id1, uint64_t id2, diff --git a/storage/tokudb/PerconaFT/src/ydb_env_func.cc b/storage/tokudb/PerconaFT/src/ydb_env_func.cc index cd5388106ac..aa8f9063a7e 100644 --- a/storage/tokudb/PerconaFT/src/ydb_env_func.cc +++ b/storage/tokudb/PerconaFT/src/ydb_env_func.cc @@ -110,7 +110,7 @@ void db_env_set_func_pread (ssize_t (*fun)(int, void *, size_t, off_t)) { } void db_env_set_func_loader_fwrite (size_t (*fwrite_fun)(const void*,size_t,size_t,FILE*)) { - ft_loader_set_os_fwrite(fwrite_fun); + toku_set_func_fwrite(fwrite_fun); } void db_env_set_func_malloc (void *(*f)(size_t)) { diff --git a/storage/tokudb/PerconaFT/src/ydb_txn.cc b/storage/tokudb/PerconaFT/src/ydb_txn.cc index 40b479055f2..dd5fb3b8f0c 100644 --- a/storage/tokudb/PerconaFT/src/ydb_txn.cc +++ b/storage/tokudb/PerconaFT/src/ydb_txn.cc @@ -540,10 +540,12 @@ int toku_txn_begin(DB_ENV *env, DB_TXN * stxn, DB_TXN ** txn, uint32_t flags) { db_txn_struct_i(result)->iso = child_isolation; db_txn_struct_i(result)->lt_map.create_no_array(); - toku_mutex_init(&db_txn_struct_i(result)->txn_mutex, NULL); + toku_mutex_init(*db_txn_struct_i_txn_mutex_key, + &db_txn_struct_i(result)->txn_mutex, + nullptr); TXN_SNAPSHOT_TYPE snapshot_type; - switch(db_txn_struct_i(result)->iso){ + switch (db_txn_struct_i(result)->iso) { case(TOKU_ISO_SNAPSHOT): { snapshot_type = TXN_SNAPSHOT_ROOT; @@ -603,7 +605,9 @@ void toku_keep_prepared_txn_callback (DB_ENV *env, TOKUTXN tokutxn) { toku_txn_set_container_db_txn(tokutxn, result); - toku_mutex_init(&db_txn_struct_i(result)->txn_mutex, NULL); + toku_mutex_init(*db_txn_struct_i_txn_mutex_key, + &db_txn_struct_i(result)->txn_mutex, + nullptr); } // Test-only function diff --git a/storage/tokudb/PerconaFT/tools/CMakeLists.txt b/storage/tokudb/PerconaFT/tools/CMakeLists.txt index e8aed51f813..dd54249ab40 100644 --- a/storage/tokudb/PerconaFT/tools/CMakeLists.txt +++ b/storage/tokudb/PerconaFT/tools/CMakeLists.txt @@ -12,6 +12,7 @@ foreach(tool ${tools}) (CMAKE_CXX_FLAGS_DEBUG MATCHES " -DENABLED_DEBUG_SYNC")) target_link_libraries(${tool} sql) endif() + target_link_libraries(${tool} mysys) endif () add_space_separated_property(TARGET ${tool} COMPILE_FLAGS -fvisibility=hidden) diff --git a/storage/tokudb/PerconaFT/util/dbt.cc b/storage/tokudb/PerconaFT/util/dbt.cc index 5bc1cb7446f..b6d2a584a45 100644 --- a/storage/tokudb/PerconaFT/util/dbt.cc +++ b/storage/tokudb/PerconaFT/util/dbt.cc @@ -199,7 +199,8 @@ int toku_dbt_set(uint32_t len, const void *val, DBT *d, struct simple_dbt *sdbt) case (DB_DBT_MALLOC): d->data = NULL; d->ulen = 0; - //Fall through to DB_DBT_REALLOC + // fallthrough + // to DB_DBT_REALLOC case (DB_DBT_REALLOC): if (d->ulen < len) { d->ulen = len*2; diff --git a/storage/tokudb/PerconaFT/util/fmutex.h b/storage/tokudb/PerconaFT/util/fmutex.h index 9ff95978a16..fed1bc24a92 100644 --- a/storage/tokudb/PerconaFT/util/fmutex.h +++ b/storage/tokudb/PerconaFT/util/fmutex.h @@ -38,6 +38,8 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #pragma once +extern toku_instr_key *fmutex_cond_key; + // fair mutex struct fmutex { pthread_mutex_t mutex; @@ -98,8 +100,8 @@ void fmutex_lock(struct fmutex *fm) { } pthread_cond_t cond; - pthread_cond_init(&cond, NULL); - struct queue_item item = { .cond = &cond, .next = NULL }; + pthread_cond_init(*fmutex_cond_key, &cond, nullptr); + struct queue_item item = {.cond = &cond, .next = NULL}; enq_item(fm, &item); // Wait for our turn. diff --git a/storage/tokudb/PerconaFT/util/frwlock.cc b/storage/tokudb/PerconaFT/util/frwlock.cc index ce1e33e85d3..1f821fe5f54 100644 --- a/storage/tokudb/PerconaFT/util/frwlock.cc +++ b/storage/tokudb/PerconaFT/util/frwlock.cc @@ -41,271 +41,311 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include <util/context.h> #include <util/frwlock.h> +toku_instr_key *frwlock_m_wait_read_key; + namespace toku { -static __thread int thread_local_tid = -1; -static int get_local_tid() { - if (thread_local_tid == -1) { - thread_local_tid = toku_os_gettid(); - } - return thread_local_tid; -} - -void frwlock::init(toku_mutex_t *const mutex) { - m_mutex = mutex; - - m_num_readers = 0; - m_num_writers = 0; - m_num_want_write = 0; - m_num_want_read = 0; - m_num_signaled_readers = 0; - m_num_expensive_want_write = 0; - - toku_cond_init(&m_wait_read, nullptr); - m_queue_item_read.cond = &m_wait_read; - m_queue_item_read.next = nullptr; - m_wait_read_is_in_queue = false; - m_current_writer_expensive = false; - m_read_wait_expensive = false; - m_current_writer_tid = -1; - m_blocking_writer_context_id = CTX_INVALID; - - m_wait_head = nullptr; - m_wait_tail = nullptr; -} - -void frwlock::deinit(void) { - toku_cond_destroy(&m_wait_read); -} - -bool frwlock::queue_is_empty(void) const { - return m_wait_head == nullptr; -} - -void frwlock::enq_item(queue_item *const item) { - paranoid_invariant_null(item->next); - if (m_wait_tail != nullptr) { - m_wait_tail->next = item; - } else { - paranoid_invariant_null(m_wait_head); - m_wait_head = item; + static __thread int thread_local_tid = -1; + static int get_local_tid() { + if (thread_local_tid == -1) { + thread_local_tid = toku_os_gettid(); + } + return thread_local_tid; } - m_wait_tail = item; -} - -toku_cond_t *frwlock::deq_item(void) { - paranoid_invariant_notnull(m_wait_head); - paranoid_invariant_notnull(m_wait_tail); - queue_item *item = m_wait_head; - m_wait_head = m_wait_head->next; - if (m_wait_tail == item) { + + void frwlock::init(toku_mutex_t *const mutex +#if defined(TOKU_MYSQL_WITH_PFS) + , + const toku_instr_key &rwlock_instr_key +#endif + ) { + m_mutex = mutex; + + m_num_readers = 0; + m_num_writers = 0; + m_num_want_write = 0; + m_num_want_read = 0; + m_num_signaled_readers = 0; + m_num_expensive_want_write = 0; +#if defined(TOKU_MYSQL_WITH_PFS) + toku_pthread_rwlock_init(rwlock_instr_key, &m_rwlock, nullptr); +#endif + toku_cond_init(toku_uninstrumented, &m_wait_read, nullptr); + m_queue_item_read.cond = &m_wait_read; + m_queue_item_read.next = nullptr; + m_wait_read_is_in_queue = false; + m_current_writer_expensive = false; + m_read_wait_expensive = false; + m_current_writer_tid = -1; + m_blocking_writer_context_id = CTX_INVALID; + + m_wait_head = nullptr; m_wait_tail = nullptr; } - return item->cond; -} - -// Prerequisite: Holds m_mutex. -void frwlock::write_lock(bool expensive) { - toku_mutex_assert_locked(m_mutex); - if (this->try_write_lock(expensive)) { - return; + + void frwlock::deinit(void) { + toku_cond_destroy(&m_wait_read); +#if defined(TOKU_MYSQL_WITH_PFS) + toku_pthread_rwlock_destroy(&m_rwlock); +#endif } - toku_cond_t cond = TOKU_COND_INITIALIZER; - queue_item item = { .cond = &cond, .next = nullptr }; - this->enq_item(&item); + bool frwlock::queue_is_empty(void) const { return m_wait_head == nullptr; } - // Wait for our turn. - ++m_num_want_write; - if (expensive) { - ++m_num_expensive_want_write; - } - if (m_num_writers == 0 && m_num_want_write == 1) { - // We are the first to want a write lock. No new readers can get the lock. - // Set our thread id and context for proper instrumentation. - // see: toku_context_note_frwlock_contention() - m_current_writer_tid = get_local_tid(); - m_blocking_writer_context_id = toku_thread_get_context()->get_id(); - } - toku_cond_wait(&cond, m_mutex); - toku_cond_destroy(&cond); - - // Now it's our turn. - paranoid_invariant(m_num_want_write > 0); - paranoid_invariant_zero(m_num_readers); - paranoid_invariant_zero(m_num_writers); - paranoid_invariant_zero(m_num_signaled_readers); - - // Not waiting anymore; grab the lock. - --m_num_want_write; - if (expensive) { - --m_num_expensive_want_write; + void frwlock::enq_item(queue_item *const item) { + paranoid_invariant_null(item->next); + if (m_wait_tail != nullptr) { + m_wait_tail->next = item; + } else { + paranoid_invariant_null(m_wait_head); + m_wait_head = item; + } + m_wait_tail = item; } - m_num_writers = 1; - m_current_writer_expensive = expensive; - m_current_writer_tid = get_local_tid(); - m_blocking_writer_context_id = toku_thread_get_context()->get_id(); -} - -bool frwlock::try_write_lock(bool expensive) { - toku_mutex_assert_locked(m_mutex); - if (m_num_readers > 0 || m_num_writers > 0 || m_num_signaled_readers > 0 || m_num_want_write > 0) { - return false; + + toku_cond_t *frwlock::deq_item(void) { + paranoid_invariant_notnull(m_wait_head); + paranoid_invariant_notnull(m_wait_tail); + queue_item *item = m_wait_head; + m_wait_head = m_wait_head->next; + if (m_wait_tail == item) { + m_wait_tail = nullptr; + } + return item->cond; } - // No one holds the lock. Grant the write lock. - paranoid_invariant_zero(m_num_want_write); - paranoid_invariant_zero(m_num_want_read); - m_num_writers = 1; - m_current_writer_expensive = expensive; - m_current_writer_tid = get_local_tid(); - m_blocking_writer_context_id = toku_thread_get_context()->get_id(); - return true; -} - -void frwlock::read_lock(void) { - toku_mutex_assert_locked(m_mutex); - if (m_num_writers > 0 || m_num_want_write > 0) { - if (!m_wait_read_is_in_queue) { - // Throw the read cond_t onto the queue. - paranoid_invariant(m_num_signaled_readers == m_num_want_read); - m_queue_item_read.next = nullptr; - this->enq_item(&m_queue_item_read); - m_wait_read_is_in_queue = true; - paranoid_invariant(!m_read_wait_expensive); - m_read_wait_expensive = ( - m_current_writer_expensive || - (m_num_expensive_want_write > 0) - ); + + // Prerequisite: Holds m_mutex. + void frwlock::write_lock(bool expensive) { +#if defined(TOKU_MYSQL_WITH_PFS) + /* Instrumentation start */ + toku_rwlock_instrumentation rwlock_instr; + toku_instr_rwlock_wrlock_wait_start( + rwlock_instr, m_rwlock, __FILE__, __LINE__); +#endif + + toku_mutex_assert_locked(m_mutex); + if (this->try_write_lock(expensive)) { +#if defined(TOKU_MYSQL_WITH_PFS) + /* Instrumentation end */ + toku_instr_rwlock_wrlock_wait_end(rwlock_instr, 0); +#endif + return; } - // Note this contention event in engine status. - toku_context_note_frwlock_contention( - toku_thread_get_context()->get_id(), - m_blocking_writer_context_id - ); + toku_cond_t cond = TOKU_COND_INITIALIZER; + queue_item item = {.cond = &cond, .next = nullptr}; + this->enq_item(&item); // Wait for our turn. - ++m_num_want_read; - toku_cond_wait(&m_wait_read, m_mutex); + ++m_num_want_write; + if (expensive) { + ++m_num_expensive_want_write; + } + if (m_num_writers == 0 && m_num_want_write == 1) { + // We are the first to want a write lock. No new readers can get the + // lock. + // Set our thread id and context for proper instrumentation. + // see: toku_context_note_frwlock_contention() + m_current_writer_tid = get_local_tid(); + m_blocking_writer_context_id = toku_thread_get_context()->get_id(); + } + toku_cond_wait(&cond, m_mutex); + toku_cond_destroy(&cond); // Now it's our turn. + paranoid_invariant(m_num_want_write > 0); + paranoid_invariant_zero(m_num_readers); paranoid_invariant_zero(m_num_writers); - paranoid_invariant(m_num_want_read > 0); - paranoid_invariant(m_num_signaled_readers > 0); + paranoid_invariant_zero(m_num_signaled_readers); // Not waiting anymore; grab the lock. - --m_num_want_read; - --m_num_signaled_readers; + --m_num_want_write; + if (expensive) { + --m_num_expensive_want_write; + } + m_num_writers = 1; + m_current_writer_expensive = expensive; + m_current_writer_tid = get_local_tid(); + m_blocking_writer_context_id = toku_thread_get_context()->get_id(); + +#if defined(TOKU_MYSQL_WITH_PFS) + /* Instrumentation end */ + toku_instr_rwlock_wrlock_wait_end(rwlock_instr, 0); +#endif + } + + bool frwlock::try_write_lock(bool expensive) { + toku_mutex_assert_locked(m_mutex); + if (m_num_readers > 0 || m_num_writers > 0 || + m_num_signaled_readers > 0 || m_num_want_write > 0) { + return false; + } + // No one holds the lock. Grant the write lock. + paranoid_invariant_zero(m_num_want_write); + paranoid_invariant_zero(m_num_want_read); + m_num_writers = 1; + m_current_writer_expensive = expensive; + m_current_writer_tid = get_local_tid(); + m_blocking_writer_context_id = toku_thread_get_context()->get_id(); + return true; } - ++m_num_readers; -} -bool frwlock::try_read_lock(void) { - toku_mutex_assert_locked(m_mutex); - if (m_num_writers > 0 || m_num_want_write > 0) { - return false; + void frwlock::read_lock(void) { +#if defined(TOKU_MYSQL_WITH_PFS) + /* Instrumentation start */ + toku_rwlock_instrumentation rwlock_instr; + toku_instr_rwlock_rdlock_wait_start( + rwlock_instr, m_rwlock, __FILE__, __LINE__); +#endif + toku_mutex_assert_locked(m_mutex); + if (m_num_writers > 0 || m_num_want_write > 0) { + if (!m_wait_read_is_in_queue) { + // Throw the read cond_t onto the queue. + paranoid_invariant(m_num_signaled_readers == m_num_want_read); + m_queue_item_read.next = nullptr; + this->enq_item(&m_queue_item_read); + m_wait_read_is_in_queue = true; + paranoid_invariant(!m_read_wait_expensive); + m_read_wait_expensive = (m_current_writer_expensive || + (m_num_expensive_want_write > 0)); + } + + // Note this contention event in engine status. + toku_context_note_frwlock_contention( + toku_thread_get_context()->get_id(), + m_blocking_writer_context_id); + + // Wait for our turn. + ++m_num_want_read; + toku_cond_wait(&m_wait_read, m_mutex); + + // Now it's our turn. + paranoid_invariant_zero(m_num_writers); + paranoid_invariant(m_num_want_read > 0); + paranoid_invariant(m_num_signaled_readers > 0); + + // Not waiting anymore; grab the lock. + --m_num_want_read; + --m_num_signaled_readers; + } + ++m_num_readers; +#if defined(TOKU_MYSQL_WITH_PFS) + /* Instrumentation end */ + toku_instr_rwlock_rdlock_wait_end(rwlock_instr, 0); +#endif } - // No writer holds the lock. - // No writers are waiting. - // Grant the read lock. - ++m_num_readers; - return true; -} - -void frwlock::maybe_signal_next_writer(void) { - if (m_num_want_write > 0 && m_num_signaled_readers == 0 && m_num_readers == 0) { - toku_cond_t *cond = this->deq_item(); - paranoid_invariant(cond != &m_wait_read); - // Grant write lock to waiting writer. - paranoid_invariant(m_num_want_write > 0); - toku_cond_signal(cond); + + bool frwlock::try_read_lock(void) { + toku_mutex_assert_locked(m_mutex); + if (m_num_writers > 0 || m_num_want_write > 0) { + return false; + } + // No writer holds the lock. + // No writers are waiting. + // Grant the read lock. + ++m_num_readers; + return true; } -} - -void frwlock::read_unlock(void) { - toku_mutex_assert_locked(m_mutex); - paranoid_invariant(m_num_writers == 0); - paranoid_invariant(m_num_readers > 0); - --m_num_readers; - this->maybe_signal_next_writer(); -} - -bool frwlock::read_lock_is_expensive(void) { - toku_mutex_assert_locked(m_mutex); - if (m_wait_read_is_in_queue) { - return m_read_wait_expensive; + + void frwlock::maybe_signal_next_writer(void) { + if (m_num_want_write > 0 && m_num_signaled_readers == 0 && + m_num_readers == 0) { + toku_cond_t *cond = this->deq_item(); + paranoid_invariant(cond != &m_wait_read); + // Grant write lock to waiting writer. + paranoid_invariant(m_num_want_write > 0); + toku_cond_signal(cond); + } + } + + void frwlock::read_unlock(void) { +#ifdef TOKU_MYSQL_WITH_PFS + toku_instr_rwlock_unlock(m_rwlock); +#endif + toku_mutex_assert_locked(m_mutex); + paranoid_invariant(m_num_writers == 0); + paranoid_invariant(m_num_readers > 0); + --m_num_readers; + this->maybe_signal_next_writer(); } - else { - return m_current_writer_expensive || (m_num_expensive_want_write > 0); + + bool frwlock::read_lock_is_expensive(void) { + toku_mutex_assert_locked(m_mutex); + if (m_wait_read_is_in_queue) { + return m_read_wait_expensive; + } else { + return m_current_writer_expensive || + (m_num_expensive_want_write > 0); + } } -} + void frwlock::maybe_signal_or_broadcast_next(void) { + paranoid_invariant(m_num_signaled_readers == 0); -void frwlock::maybe_signal_or_broadcast_next(void) { - paranoid_invariant(m_num_signaled_readers == 0); + if (this->queue_is_empty()) { + paranoid_invariant(m_num_want_write == 0); + paranoid_invariant(m_num_want_read == 0); + return; + } + toku_cond_t *cond = this->deq_item(); + if (cond == &m_wait_read) { + // Grant read locks to all waiting readers + paranoid_invariant(m_wait_read_is_in_queue); + paranoid_invariant(m_num_want_read > 0); + m_num_signaled_readers = m_num_want_read; + m_wait_read_is_in_queue = false; + m_read_wait_expensive = false; + toku_cond_broadcast(cond); + } else { + // Grant write lock to waiting writer. + paranoid_invariant(m_num_want_write > 0); + toku_cond_signal(cond); + } + } - if (this->queue_is_empty()) { - paranoid_invariant(m_num_want_write == 0); - paranoid_invariant(m_num_want_read == 0); - return; + void frwlock::write_unlock(void) { +#if defined(TOKU_MYSQL_WITH_PFS) + toku_instr_rwlock_unlock(m_rwlock); +#endif + toku_mutex_assert_locked(m_mutex); + paranoid_invariant(m_num_writers == 1); + m_num_writers = 0; + m_current_writer_expensive = false; + m_current_writer_tid = -1; + m_blocking_writer_context_id = CTX_INVALID; + this->maybe_signal_or_broadcast_next(); } - toku_cond_t *cond = this->deq_item(); - if (cond == &m_wait_read) { - // Grant read locks to all waiting readers - paranoid_invariant(m_wait_read_is_in_queue); - paranoid_invariant(m_num_want_read > 0); - m_num_signaled_readers = m_num_want_read; - m_wait_read_is_in_queue = false; - m_read_wait_expensive = false; - toku_cond_broadcast(cond); + bool frwlock::write_lock_is_expensive(void) { + toku_mutex_assert_locked(m_mutex); + return (m_num_expensive_want_write > 0) || (m_current_writer_expensive); } - else { - // Grant write lock to waiting writer. - paranoid_invariant(m_num_want_write > 0); - toku_cond_signal(cond); + + uint32_t frwlock::users(void) const { + toku_mutex_assert_locked(m_mutex); + return m_num_readers + m_num_writers + m_num_want_read + + m_num_want_write; + } + uint32_t frwlock::blocked_users(void) const { + toku_mutex_assert_locked(m_mutex); + return m_num_want_read + m_num_want_write; + } + uint32_t frwlock::writers(void) const { + // this is sometimes called as "assert(lock->writers())" when we + // assume we have the write lock. if that's the assumption, we may + // not own the mutex, so we don't assert_locked here + return m_num_writers; + } + uint32_t frwlock::blocked_writers(void) const { + toku_mutex_assert_locked(m_mutex); + return m_num_want_write; + } + uint32_t frwlock::readers(void) const { + toku_mutex_assert_locked(m_mutex); + return m_num_readers; + } + uint32_t frwlock::blocked_readers(void) const { + toku_mutex_assert_locked(m_mutex); + return m_num_want_read; } -} - -void frwlock::write_unlock(void) { - toku_mutex_assert_locked(m_mutex); - paranoid_invariant(m_num_writers == 1); - m_num_writers = 0; - m_current_writer_expensive = false; - m_current_writer_tid = -1; - m_blocking_writer_context_id = CTX_INVALID; - this->maybe_signal_or_broadcast_next(); -} -bool frwlock::write_lock_is_expensive(void) { - toku_mutex_assert_locked(m_mutex); - return (m_num_expensive_want_write > 0) || (m_current_writer_expensive); -} - - -uint32_t frwlock::users(void) const { - toku_mutex_assert_locked(m_mutex); - return m_num_readers + m_num_writers + m_num_want_read + m_num_want_write; -} -uint32_t frwlock::blocked_users(void) const { - toku_mutex_assert_locked(m_mutex); - return m_num_want_read + m_num_want_write; -} -uint32_t frwlock::writers(void) const { - // this is sometimes called as "assert(lock->writers())" when we - // assume we have the write lock. if that's the assumption, we may - // not own the mutex, so we don't assert_locked here - return m_num_writers; -} -uint32_t frwlock::blocked_writers(void) const { - toku_mutex_assert_locked(m_mutex); - return m_num_want_write; -} -uint32_t frwlock::readers(void) const { - toku_mutex_assert_locked(m_mutex); - return m_num_readers; -} -uint32_t frwlock::blocked_readers(void) const { - toku_mutex_assert_locked(m_mutex); - return m_num_want_read; -} } // namespace toku diff --git a/storage/tokudb/PerconaFT/util/frwlock.h b/storage/tokudb/PerconaFT/util/frwlock.h index 52b98a8d727..b02d95e545c 100644 --- a/storage/tokudb/PerconaFT/util/frwlock.h +++ b/storage/tokudb/PerconaFT/util/frwlock.h @@ -48,76 +48,82 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. namespace toku { -class frwlock { -public: - - void init(toku_mutex_t *const mutex); - void deinit(void); - - void write_lock(bool expensive); - bool try_write_lock(bool expensive); - void write_unlock(void); - // returns true if acquiring a write lock will be expensive - bool write_lock_is_expensive(void); - - void read_lock(void); - bool try_read_lock(void); - void read_unlock(void); - // returns true if acquiring a read lock will be expensive - bool read_lock_is_expensive(void); - - uint32_t users(void) const; - uint32_t blocked_users(void) const; - uint32_t writers(void) const; - uint32_t blocked_writers(void) const; - uint32_t readers(void) const; - uint32_t blocked_readers(void) const; - -private: - struct queue_item { - toku_cond_t *cond; - struct queue_item *next; + class frwlock { + public: + void init(toku_mutex_t *const mutex +#if defined(TOKU_MYSQL_WITH_PFS) + , + const toku_instr_key &rwlock_instr_key +#endif + ); + void deinit(void); + + void write_lock(bool expensive); + bool try_write_lock(bool expensive); + void write_unlock(void); + // returns true if acquiring a write lock will be expensive + bool write_lock_is_expensive(void); + + void read_lock(void); + bool try_read_lock(void); + void read_unlock(void); + // returns true if acquiring a read lock will be expensive + bool read_lock_is_expensive(void); + + uint32_t users(void) const; + uint32_t blocked_users(void) const; + uint32_t writers(void) const; + uint32_t blocked_writers(void) const; + uint32_t readers(void) const; + uint32_t blocked_readers(void) const; + + private: + struct queue_item { + toku_cond_t *cond; + struct queue_item *next; + }; + + bool queue_is_empty(void) const; + void enq_item(queue_item *const item); + toku_cond_t *deq_item(void); + void maybe_signal_or_broadcast_next(void); + void maybe_signal_next_writer(void); + + toku_mutex_t *m_mutex; + + uint32_t m_num_readers; + uint32_t m_num_writers; + uint32_t m_num_want_write; + uint32_t m_num_want_read; + uint32_t m_num_signaled_readers; + // number of writers waiting that are expensive + // MUST be < m_num_want_write + uint32_t m_num_expensive_want_write; + // bool that states if the current writer is expensive + // if there is no current writer, then is false + bool m_current_writer_expensive; + // bool that states if waiting for a read + // is expensive + // if there are currently no waiting readers, then set to false + bool m_read_wait_expensive; + // thread-id of the current writer + int m_current_writer_tid; + // context id describing the context of the current writer blocking + // new readers (either because this writer holds the write lock or + // is the first to want the write lock). + context_id m_blocking_writer_context_id; + queue_item m_queue_item_read; + bool m_wait_read_is_in_queue; + + toku_cond_t m_wait_read; +#if defined(TOKU_MYSQL_WITH_PFS) + toku_pthread_rwlock_t m_rwlock; +#endif + queue_item *m_wait_head; + queue_item *m_wait_tail; }; - bool queue_is_empty(void) const; - void enq_item(queue_item *const item); - toku_cond_t *deq_item(void); - void maybe_signal_or_broadcast_next(void); - void maybe_signal_next_writer(void); - - toku_mutex_t *m_mutex; - - uint32_t m_num_readers; - uint32_t m_num_writers; - uint32_t m_num_want_write; - uint32_t m_num_want_read; - uint32_t m_num_signaled_readers; - // number of writers waiting that are expensive - // MUST be < m_num_want_write - uint32_t m_num_expensive_want_write; - // bool that states if the current writer is expensive - // if there is no current writer, then is false - bool m_current_writer_expensive; - // bool that states if waiting for a read - // is expensive - // if there are currently no waiting readers, then set to false - bool m_read_wait_expensive; - // thread-id of the current writer - int m_current_writer_tid; - // context id describing the context of the current writer blocking - // new readers (either because this writer holds the write lock or - // is the first to want the write lock). - context_id m_blocking_writer_context_id; - - toku_cond_t m_wait_read; - queue_item m_queue_item_read; - bool m_wait_read_is_in_queue; - - queue_item *m_wait_head; - queue_item *m_wait_tail; -}; - -ENSURE_POD(frwlock); + ENSURE_POD(frwlock); } // namespace toku diff --git a/storage/tokudb/PerconaFT/util/kibbutz.cc b/storage/tokudb/PerconaFT/util/kibbutz.cc index 7fc24bae727..409bf6bdd7b 100644 --- a/storage/tokudb/PerconaFT/util/kibbutz.cc +++ b/storage/tokudb/PerconaFT/util/kibbutz.cc @@ -72,14 +72,18 @@ struct kibbutz { uint64_t total_execution_time; }; -static void *work_on_kibbutz (void *); +static void *work_on_kibbutz(void *); -int toku_kibbutz_create (int n_workers, KIBBUTZ *kb_ret) { +toku_instr_key *kibbutz_mutex_key; +toku_instr_key *kibbutz_k_cond_key; +toku_instr_key *kibbutz_thread_key; + +int toku_kibbutz_create(int n_workers, KIBBUTZ *kb_ret) { int r = 0; *kb_ret = NULL; KIBBUTZ XCALLOC(k); - toku_mutex_init(&k->mutex, NULL); - toku_cond_init(&k->cond, NULL); + toku_mutex_init(*kibbutz_mutex_key, &k->mutex, nullptr); + toku_cond_init(*kibbutz_k_cond_key, &k->cond, nullptr); k->please_shutdown = false; k->head = NULL; k->tail = NULL; @@ -93,7 +97,11 @@ int toku_kibbutz_create (int n_workers, KIBBUTZ *kb_ret) { XMALLOC_N(n_workers, k->ids); for (int i = 0; i < n_workers; i++) { k->ids[i].k = k; - r = toku_pthread_create(&k->workers[i], NULL, work_on_kibbutz, &k->ids[i]); + r = toku_pthread_create(*kibbutz_thread_key, + &k->workers[i], + nullptr, + work_on_kibbutz, + &k->ids[i]); if (r != 0) { k->n_workers = i; toku_kibbutz_destroy(k); @@ -153,10 +161,14 @@ static void *work_on_kibbutz (void *kidv) { // if there's another item on k->head, then we'll just go grab it now, without waiting for a signal. } if (k->please_shutdown) { - // Don't follow this unless the work is all done, so that when we set please_shutdown, all the work finishes before any threads quit. - ksignal(k); // must wake up anyone else who is waiting, so they can shut down. + // Don't follow this unless the work is all done, so that when we + // set please_shutdown, all the work finishes before any threads + // quit. + ksignal(k); // must wake up anyone else who is waiting, so they can + // shut down. kunlock(k); - return NULL; + toku_instr_delete_current_thread(); + return nullptr; } // There is no work to do and it's not time to shutdown, so wait. kwait(k); diff --git a/storage/tokudb/PerconaFT/util/minicron.cc b/storage/tokudb/PerconaFT/util/minicron.cc index 737c6ef6a4f..c1412015be0 100644 --- a/storage/tokudb/PerconaFT/util/minicron.cc +++ b/storage/tokudb/PerconaFT/util/minicron.cc @@ -43,8 +43,11 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "portability/toku_assert.h" #include "util/minicron.h" -static void -toku_gettime (toku_timespec_t *a) { +toku_instr_key *minicron_p_mutex_key; +toku_instr_key *minicron_p_condvar_key; +toku_instr_key *minicron_thread_key; + +static void toku_gettime(toku_timespec_t *a) { struct timeval tv; gettimeofday(&tv, 0); a->tv_sec = tv.tv_sec; @@ -74,7 +77,8 @@ minicron_do (void *pv) while (1) { if (p->do_shutdown) { toku_mutex_unlock(&p->mutex); - return 0; + toku_instr_delete_current_thread(); + return toku_pthread_done(nullptr); } if (p->period_in_ms == 0) { // if we aren't supposed to do it then just do an untimed wait. @@ -104,7 +108,8 @@ minicron_do (void *pv) // Now we woke up, and we should figure out what to do if (p->do_shutdown) { toku_mutex_unlock(&p->mutex); - return 0; + toku_instr_delete_current_thread(); + return toku_pthread_done(nullptr); } if (p->period_in_ms > 1000) { toku_timespec_t now; @@ -137,17 +142,17 @@ toku_minicron_setup(struct minicron *p, uint32_t period_in_ms, int(*f)(void *), p->f = f; p->arg = arg; toku_gettime(&p->time_of_last_call_to_f); - //printf("now=%.6f", p->time_of_last_call_to_f.tv_sec + p->time_of_last_call_to_f.tv_nsec*1e-9); - p->period_in_ms = period_in_ms; + // printf("now=%.6f", p->time_of_last_call_to_f.tv_sec + + // p->time_of_last_call_to_f.tv_nsec*1e-9); + p->period_in_ms = period_in_ms; p->do_shutdown = false; - toku_mutex_init(&p->mutex, 0); - toku_cond_init (&p->condvar, 0); - return toku_pthread_create(&p->thread, 0, minicron_do, p); + toku_mutex_init(*minicron_p_mutex_key, &p->mutex, nullptr); + toku_cond_init(*minicron_p_condvar_key, &p->condvar, nullptr); + return toku_pthread_create( + *minicron_thread_key, &p->thread, nullptr, minicron_do, p); } - -void -toku_minicron_change_period(struct minicron *p, uint32_t new_period) -{ + +void toku_minicron_change_period(struct minicron *p, uint32_t new_period) { toku_mutex_lock(&p->mutex); p->period_in_ms = new_period; toku_cond_signal(&p->condvar); diff --git a/storage/tokudb/PerconaFT/util/nb_mutex.h b/storage/tokudb/PerconaFT/util/nb_mutex.h index 3490c1b365c..d777961ad78 100644 --- a/storage/tokudb/PerconaFT/util/nb_mutex.h +++ b/storage/tokudb/PerconaFT/util/nb_mutex.h @@ -49,35 +49,67 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. // increase parallelism at the expense of single thread performance, we // are experimenting with a single higher level lock. +extern toku_instr_key *nb_mutex_key; + typedef struct nb_mutex *NB_MUTEX; struct nb_mutex { - struct rwlock lock; + struct st_rwlock lock; +#if defined(TOKU_MYSQL_WITH_PFS) + toku_mutex_t toku_mutex; +#endif }; +#if defined(TOKU_MYSQL_WITH_PFS) +#define nb_mutex_init(MK, RK, M) \ + inline_nb_mutex_init(MK, RK, M) +#else +#define nb_mutex_init(MK, RK, M) inline_nb_mutex_init(M) +#endif + // initialize an nb mutex -static __attribute__((__unused__)) -void -nb_mutex_init(NB_MUTEX nb_mutex) { - rwlock_init(&nb_mutex->lock); +inline void inline_nb_mutex_init( +#if defined(TOKU_MYSQL_WITH_PFS) + const toku_instr_key &mutex_instr_key, + const toku_instr_key &rwlock_instr_key, +#endif + NB_MUTEX nb_mutex) { +#if defined(TOKU_MYSQL_WITH_PFS) + toku_mutex_init(mutex_instr_key, &nb_mutex->toku_mutex, nullptr); +#endif + rwlock_init(rwlock_instr_key, &nb_mutex->lock); } // destroy a read write lock -static __attribute__((__unused__)) -void -nb_mutex_destroy(NB_MUTEX nb_mutex) { +inline void nb_mutex_destroy(NB_MUTEX nb_mutex) { +#if defined(TOKU_MYSQL_WITH_PFS) + toku_instr_mutex_destroy(nb_mutex->toku_mutex.psi_mutex); +#endif rwlock_destroy(&nb_mutex->lock); } // obtain a write lock // expects: mutex is locked -static inline void nb_mutex_lock(NB_MUTEX nb_mutex, toku_mutex_t *mutex) { +inline void nb_mutex_lock(NB_MUTEX nb_mutex, toku_mutex_t *mutex) { +#ifdef TOKU_MYSQL_WITH_PFS + toku_mutex_instrumentation mutex_instr; + toku_instr_mutex_lock_start(mutex_instr, + *mutex, + __FILE__, + __LINE__); // TODO: pull these to caller? +#endif rwlock_write_lock(&nb_mutex->lock, mutex); +#if defined(TOKU_MYSQL_WITH_PFS) + toku_instr_mutex_lock_end(mutex_instr, 0); +#endif } // release a write lock // expects: mutex is locked -static inline void nb_mutex_unlock(NB_MUTEX nb_mutex) { +inline void nb_mutex_unlock(NB_MUTEX nb_mutex) { +#if defined(TOKU_MYSQL_WITH_PFS) + toku_instr_mutex_unlock(nb_mutex->toku_mutex.psi_mutex); +#endif rwlock_write_unlock(&nb_mutex->lock); } diff --git a/storage/tokudb/PerconaFT/util/queue.cc b/storage/tokudb/PerconaFT/util/queue.cc index 0716dfb2f59..39dfbbc699a 100644 --- a/storage/tokudb/PerconaFT/util/queue.cc +++ b/storage/tokudb/PerconaFT/util/queue.cc @@ -44,6 +44,9 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "memory.h" #include <toku_pthread.h> +toku_instr_key *queue_result_mutex_key; +toku_instr_key *queue_result_cond_key; + struct qitem; struct qitem { @@ -81,11 +84,11 @@ int toku_queue_create (QUEUE *q, uint64_t weight_limit) if (result==NULL) return get_error_errno(); result->contents_weight = 0; result->weight_limit = weight_limit; - result->head = NULL; - result->tail = NULL; - result->eof = false; - toku_mutex_init(&result->mutex, NULL); - toku_cond_init(&result->cond, NULL); + result->head = NULL; + result->tail = NULL; + result->eof = false; + toku_mutex_init(*queue_result_mutex_key, &result->mutex, nullptr); + toku_cond_init(*queue_result_cond_key, &result->cond, nullptr); *q = result; return 0; } diff --git a/storage/tokudb/PerconaFT/util/rwlock.h b/storage/tokudb/PerconaFT/util/rwlock.h index 47f78df70d1..d9a13ba9014 100644 --- a/storage/tokudb/PerconaFT/util/rwlock.h +++ b/storage/tokudb/PerconaFT/util/rwlock.h @@ -39,6 +39,8 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #pragma once #include <toku_assert.h> +#include <toku_portability.h> +#include <toku_instrumentation.h> /* Readers/writers locks implementation * @@ -147,53 +149,81 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. // increase parallelism at the expense of single thread performance, we // are experimenting with a single higher level lock. -typedef struct rwlock *RWLOCK; -struct rwlock { - int reader; // the number of readers - int want_read; // the number of blocked readers +extern toku_instr_key *rwlock_cond_key; +extern toku_instr_key *rwlock_wait_read_key; +extern toku_instr_key *rwlock_wait_write_key; + +typedef struct st_rwlock *RWLOCK; +struct st_rwlock { + int reader; // the number of readers + int want_read; // the number of blocked readers toku_cond_t wait_read; int writer; // the number of writers int want_write; // the number of blocked writers toku_cond_t wait_write; - toku_cond_t* wait_users_go_to_zero; + toku_cond_t *wait_users_go_to_zero; +#if defined(TOKU_MYSQL_WITH_PFS) + toku_pthread_rwlock_t prwlock; +#endif }; // returns: the sum of the number of readers, pending readers, writers, and // pending writers static inline int rwlock_users(RWLOCK rwlock) { - return rwlock->reader + rwlock->want_read + rwlock->writer + rwlock->want_write; + return rwlock->reader + rwlock->want_read + rwlock->writer + + rwlock->want_write; } -// initialize a read write lock +#if defined(TOKU_MYSQL_WITH_PFS) +#define rwlock_init(K, R) inline_rwlock_init(K, R) +#else +#define rwlock_init(K, R) inline_rwlock_init(R) +#endif -static __attribute__((__unused__)) -void -rwlock_init(RWLOCK rwlock) { +// initialize a read write lock +static inline __attribute__((__unused__)) void inline_rwlock_init( +#if defined(TOKU_MYSQL_WITH_PFS) + const toku_instr_key &rwlock_instr_key, +#endif + RWLOCK rwlock) { +#if defined(TOKU_MYSQL_WITH_PFS) + toku_pthread_rwlock_init(rwlock_instr_key, &rwlock->prwlock, nullptr); +#endif rwlock->reader = rwlock->want_read = 0; - toku_cond_init(&rwlock->wait_read, 0); rwlock->writer = rwlock->want_write = 0; - toku_cond_init(&rwlock->wait_write, 0); + toku_cond_init(toku_uninstrumented, &rwlock->wait_read, nullptr); + toku_cond_init(toku_uninstrumented, &rwlock->wait_write, nullptr); rwlock->wait_users_go_to_zero = NULL; } // destroy a read write lock -static __attribute__((__unused__)) -void -rwlock_destroy(RWLOCK rwlock) { +static inline __attribute__((__unused__)) void rwlock_destroy(RWLOCK rwlock) { paranoid_invariant(rwlock->reader == 0); paranoid_invariant(rwlock->want_read == 0); paranoid_invariant(rwlock->writer == 0); paranoid_invariant(rwlock->want_write == 0); toku_cond_destroy(&rwlock->wait_read); toku_cond_destroy(&rwlock->wait_write); +#if defined(TOKU_MYSQL_WITH_PFS) + toku_pthread_rwlock_destroy(&rwlock->prwlock); +#endif } // obtain a read lock // expects: mutex is locked static inline void rwlock_read_lock(RWLOCK rwlock, toku_mutex_t *mutex) { +#ifdef TOKU_MYSQL_WITH_PFS + /* Instrumentation start */ + toku_rwlock_instrumentation rwlock_instr; + // TODO: pull location information up to caller + toku_instr_rwlock_rdlock_wait_start( + rwlock_instr, rwlock->prwlock, __FILE__, __LINE__); + +#endif + paranoid_invariant(!rwlock->wait_users_go_to_zero); if (rwlock->writer || rwlock->want_write) { rwlock->want_read++; @@ -203,12 +233,19 @@ static inline void rwlock_read_lock(RWLOCK rwlock, toku_mutex_t *mutex) { rwlock->want_read--; } rwlock->reader++; +#ifdef TOKU_MYSQL_WITH_PFS + /* Instrumentation end */ + toku_instr_rwlock_wrlock_wait_end(rwlock_instr, 0); +#endif } // release a read lock // expects: mutex is locked static inline void rwlock_read_unlock(RWLOCK rwlock) { +#ifdef TOKU_MYSQL_WITH_PFS + toku_instr_rwlock_unlock(rwlock->prwlock); +#endif paranoid_invariant(rwlock->reader > 0); paranoid_invariant(rwlock->writer == 0); rwlock->reader--; @@ -224,6 +261,12 @@ static inline void rwlock_read_unlock(RWLOCK rwlock) { // expects: mutex is locked static inline void rwlock_write_lock(RWLOCK rwlock, toku_mutex_t *mutex) { +#ifdef TOKU_MYSQL_WITH_PFS + /* Instrumentation start */ + toku_rwlock_instrumentation rwlock_instr; + toku_instr_rwlock_wrlock_wait_start( + rwlock_instr, rwlock->prwlock, __FILE__, __LINE__); +#endif paranoid_invariant(!rwlock->wait_users_go_to_zero); if (rwlock->reader || rwlock->writer) { rwlock->want_write++; @@ -233,12 +276,19 @@ static inline void rwlock_write_lock(RWLOCK rwlock, toku_mutex_t *mutex) { rwlock->want_write--; } rwlock->writer++; +#if defined(TOKU_MYSQL_WITH_PFS) + /* Instrumentation end */ + toku_instr_rwlock_wrlock_wait_end(rwlock_instr, 0); +#endif } // release a write lock // expects: mutex is locked static inline void rwlock_write_unlock(RWLOCK rwlock) { +#if defined(TOKU_MYSQL_WITH_PFS) + toku_instr_rwlock_unlock(rwlock->prwlock); +#endif paranoid_invariant(rwlock->reader == 0); paranoid_invariant(rwlock->writer == 1); rwlock->writer--; @@ -284,14 +334,10 @@ static inline int rwlock_read_will_block(RWLOCK rwlock) { return (rwlock->writer > 0 || rwlock->want_write > 0); } -static inline void rwlock_wait_for_users( - RWLOCK rwlock, - toku_mutex_t *mutex - ) -{ +static inline void rwlock_wait_for_users(RWLOCK rwlock, toku_mutex_t *mutex) { paranoid_invariant(!rwlock->wait_users_go_to_zero); toku_cond_t cond; - toku_cond_init(&cond, NULL); + toku_cond_init(toku_uninstrumented, &cond, nullptr); while (rwlock_users(rwlock) > 0) { rwlock->wait_users_go_to_zero = &cond; toku_cond_wait(&cond, mutex); diff --git a/storage/tokudb/PerconaFT/util/tests/marked-omt-test.cc b/storage/tokudb/PerconaFT/util/tests/marked-omt-test.cc index bce1b1a885b..7e60c711c66 100644 --- a/storage/tokudb/PerconaFT/util/tests/marked-omt-test.cc +++ b/storage/tokudb/PerconaFT/util/tests/marked-omt-test.cc @@ -156,7 +156,7 @@ int int_heaviside(const uint32_t &v, const uint32_t &target) { struct stress_shared { stress_omt *omt; volatile bool running; - struct rwlock lock; + struct st_rwlock lock; toku_mutex_t mutex; int num_marker_threads; }; @@ -400,8 +400,8 @@ static void stress_test(int nelts) { struct stress_shared extra; ZERO_STRUCT(extra); extra.omt = &omt; - toku_mutex_init(&extra.mutex, NULL); - rwlock_init(&extra.lock); + toku_mutex_init(toku_uninstrumented, &extra.mutex, nullptr); + rwlock_init(toku_uninstrumented, &extra.lock); extra.running = true; extra.num_marker_threads = num_marker_threads; @@ -422,11 +422,19 @@ static void stress_test(int nelts) { r = myinitstate_r(seed, reader.buf_write, 8, &reader.rand_write); invariant_zero(r); - toku_pthread_create(&marker_threads[i], NULL, stress_mark_worker, &reader); + toku_pthread_create(toku_uninstrumented, + &marker_threads[i], + nullptr, + stress_mark_worker, + &reader); } toku_pthread_t deleter_thread; - toku_pthread_create(&deleter_thread, NULL, stress_delete_worker, &readers[0]); + toku_pthread_create(toku_uninstrumented, + &deleter_thread, + nullptr, + stress_delete_worker, + &readers[0]); toku_pthread_join(deleter_thread, NULL); for (int i = 0; i < num_marker_threads; ++i) { diff --git a/storage/tokudb/PerconaFT/util/tests/minicron-test.cc b/storage/tokudb/PerconaFT/util/tests/minicron-test.cc index a2ddbdeabdf..026ab7446d3 100644 --- a/storage/tokudb/PerconaFT/util/tests/minicron-test.cc +++ b/storage/tokudb/PerconaFT/util/tests/minicron-test.cc @@ -206,11 +206,12 @@ test_main (int argc, const char *argv[]) { toku_pthread_t tests[N]; unsigned int i; - for (i=0; i<N; i++) { - int r=toku_pthread_create(tests+i, 0, testfuns[i], 0); - assert(r==0); + for (i = 0; i < N; i++) { + int r = toku_pthread_create( + toku_uninstrumented, tests + i, nullptr, testfuns[i], nullptr); + assert(r == 0); } - for (i=0; i<N; i++) { + for (i = 0; i < N; i++) { void *v; int r=toku_pthread_join(tests[i], &v); assert(r==0); diff --git a/storage/tokudb/PerconaFT/util/tests/queue-test.cc b/storage/tokudb/PerconaFT/util/tests/queue-test.cc index 433a0aca32a..f87e05bc664 100644 --- a/storage/tokudb/PerconaFT/util/tests/queue-test.cc +++ b/storage/tokudb/PerconaFT/util/tests/queue-test.cc @@ -87,9 +87,11 @@ static void queue_test_0 (uint64_t weight) d_max_weight = 0; QUEUE q; int r; - r = toku_queue_create(&q, weight); assert(r==0); + r = toku_queue_create(&q, weight); + assert(r == 0); toku_pthread_t thread; - r = toku_pthread_create(&thread, NULL, start_0, q); assert(r==0); + r = toku_pthread_create(toku_uninstrumented, &thread, nullptr, start_0, q); + assert(r == 0); enq(q, 0L, weight); enq(q, 1L, weight); enq(q, 2L, weight); diff --git a/storage/tokudb/PerconaFT/util/tests/rwlock_condvar.h b/storage/tokudb/PerconaFT/util/tests/rwlock_condvar.h index 816b98af81c..b49c2780ff8 100644 --- a/storage/tokudb/PerconaFT/util/tests/rwlock_condvar.h +++ b/storage/tokudb/PerconaFT/util/tests/rwlock_condvar.h @@ -67,13 +67,13 @@ struct toku_cv_fair_rwlock_waiter_state { static __thread struct toku_cv_fair_rwlock_waiter_state waitstate = {0, NULL, {PTHREAD_COND_INITIALIZER} }; void toku_cv_fair_rwlock_init (toku_cv_fair_rwlock_t *rwlock) { - rwlock->state=0; + rwlock->state = 0; rwlock->waiters_head = NULL; rwlock->waiters_tail = NULL; - toku_mutex_init(&rwlock->mutex, NULL); + toku_mutex_init(toku_uninstrumented, &rwlock->mutex, nullptr); } -void toku_cv_fair_rwlock_destroy (toku_cv_fair_rwlock_t *rwlock) { +void toku_cv_fair_rwlock_destroy(toku_cv_fair_rwlock_t *rwlock) { toku_mutex_destroy(&rwlock->mutex); } diff --git a/storage/tokudb/PerconaFT/util/tests/sm-basic.cc b/storage/tokudb/PerconaFT/util/tests/sm-basic.cc index 80bc965fd31..0e5eb8364e2 100644 --- a/storage/tokudb/PerconaFT/util/tests/sm-basic.cc +++ b/storage/tokudb/PerconaFT/util/tests/sm-basic.cc @@ -64,7 +64,8 @@ int main(void) { // run the test toku_pthread_t tid; int r; - r = toku_pthread_create(&tid, NULL, sm_test_f, NULL); + r = toku_pthread_create( + toku_uninstrumented, &tid, nullptr, sm_test_f, nullptr); assert_zero(r); void *ret; r = toku_pthread_join(tid, &ret); diff --git a/storage/tokudb/PerconaFT/util/tests/sm-crash-double-free.cc b/storage/tokudb/PerconaFT/util/tests/sm-crash-double-free.cc index c5d7e3e53a7..5aa3565510b 100644 --- a/storage/tokudb/PerconaFT/util/tests/sm-crash-double-free.cc +++ b/storage/tokudb/PerconaFT/util/tests/sm-crash-double-free.cc @@ -64,10 +64,12 @@ int main(void) { toku_scoped_malloc_init(); toku_pthread_t tid; int r; - r = toku_pthread_create(&tid, NULL, sm_test_f, NULL); + r = toku_pthread_create( + toku_uninstrumented, &tid, nullptr, sm_test_f, nullptr); assert_zero(r); void *ret; - while (state != 1) sleep(1); + while (state != 1) + sleep(1); toku_scoped_malloc_destroy_set(); state = 2; r = toku_pthread_join(tid, &ret); diff --git a/storage/tokudb/PerconaFT/util/tests/test-frwlock-fair-writers.cc b/storage/tokudb/PerconaFT/util/tests/test-frwlock-fair-writers.cc index 7fd4801fe11..9a625c32aeb 100644 --- a/storage/tokudb/PerconaFT/util/tests/test-frwlock-fair-writers.cc +++ b/storage/tokudb/PerconaFT/util/tests/test-frwlock-fair-writers.cc @@ -66,9 +66,9 @@ static void *t1_func(void *arg) { int main(void) { int r; - toku_mutex_init(&rwlock_mutex, NULL); + toku_mutex_init(toku_uninstrumented, &rwlock_mutex, nullptr); rwlock.init(&rwlock_mutex); - + const int nthreads = 2; pthread_t tids[nthreads]; for (int i = 0; i < nthreads; i++) { diff --git a/storage/tokudb/PerconaFT/util/tests/test-rwlock-cheapness.cc b/storage/tokudb/PerconaFT/util/tests/test-rwlock-cheapness.cc index 0075ddf9bcb..c0b43c2db1c 100644 --- a/storage/tokudb/PerconaFT/util/tests/test-rwlock-cheapness.cc +++ b/storage/tokudb/PerconaFT/util/tests/test-rwlock-cheapness.cc @@ -101,7 +101,8 @@ static void *do_read_wait(void *arg) { static void launch_cheap_waiter(void) { toku_pthread_t tid; - int r = toku_pthread_create(&tid, NULL, do_cheap_wait, NULL); + int r = toku_pthread_create( + toku_uninstrumented, &tid, nullptr, do_cheap_wait, nullptr); assert_zero(r); toku_pthread_detach(tid); sleep(1); @@ -109,7 +110,8 @@ static void launch_cheap_waiter(void) { static void launch_expensive_waiter(void) { toku_pthread_t tid; - int r = toku_pthread_create(&tid, NULL, do_expensive_wait, NULL); + int r = toku_pthread_create( + toku_uninstrumented, &tid, nullptr, do_expensive_wait, nullptr); assert_zero(r); toku_pthread_detach(tid); sleep(1); @@ -117,7 +119,8 @@ static void launch_expensive_waiter(void) { static void launch_reader(void) { toku_pthread_t tid; - int r = toku_pthread_create(&tid, NULL, do_read_wait, NULL); + int r = toku_pthread_create( + toku_uninstrumented, &tid, nullptr, do_read_wait, nullptr); assert_zero(r); toku_pthread_detach(tid); sleep(1); @@ -132,7 +135,7 @@ static bool locks_are_expensive(void) { } static void test_write_cheapness(void) { - toku_mutex_init(&mutex, NULL); + toku_mutex_init(toku_uninstrumented, &mutex, nullptr); w.init(&mutex); // single expensive write lock diff --git a/storage/tokudb/PerconaFT/util/tests/test-rwlock.cc b/storage/tokudb/PerconaFT/util/tests/test-rwlock.cc index 18ca1229f56..56dd3f6b480 100644 --- a/storage/tokudb/PerconaFT/util/tests/test-rwlock.cc +++ b/storage/tokudb/PerconaFT/util/tests/test-rwlock.cc @@ -245,14 +245,14 @@ static void util_rwlock_unlock (RWLOCK rwlock, toku_mutex_t *mutex) { } // Time the read lock that's in util/rwlock.h -void time_util_rwlock (void) __attribute((__noinline__)); -void time_util_rwlock (void) { - struct rwlock rwlock; +void time_util_rwlock(void) __attribute((__noinline__)); +void time_util_rwlock(void) { + struct st_rwlock rwlock; toku_mutex_t external_mutex; - toku_mutex_init(&external_mutex, NULL); - rwlock_init(&rwlock); - struct timeval start,end; - + toku_mutex_init(toku_uninstrumented, &external_mutex, nullptr); + rwlock_init(toku_uninstrumented, &rwlock); + struct timeval start, end; + util_rwlock_lock(&rwlock, &external_mutex); util_rwlock_unlock(&rwlock, &external_mutex); for (int t=0; t<T; t++) { @@ -271,16 +271,17 @@ void time_util_rwlock (void) { toku_mutex_destroy(&external_mutex); } -// Time the read lock that's in util/rwlock.h, assuming the mutex is already held. -void time_util_prelocked_rwlock (void) __attribute__((__noinline__)); -void time_util_prelocked_rwlock (void) { - struct rwlock rwlock; +// Time the read lock that's in util/rwlock.h, assuming the mutex is already +// held. +void time_util_prelocked_rwlock(void) __attribute__((__noinline__)); +void time_util_prelocked_rwlock(void) { + struct st_rwlock rwlock; toku_mutex_t external_mutex; - toku_mutex_init(&external_mutex, NULL); + toku_mutex_init(toku_uninstrumented, &external_mutex, nullptr); toku_mutex_lock(&external_mutex); - rwlock_init(&rwlock); - struct timeval start,end; - + rwlock_init(toku_uninstrumented, &rwlock); + struct timeval start, end; + rwlock_read_lock(&rwlock, &external_mutex); rwlock_read_unlock(&rwlock); for (int t=0; t<T; t++) { @@ -303,8 +304,8 @@ void time_util_prelocked_rwlock (void) { void time_frwlock_prelocked(void) __attribute__((__noinline__)); void time_frwlock_prelocked(void) { toku_mutex_t external_mutex; - toku_mutex_init(&external_mutex, NULL); - struct timeval start,end; + toku_mutex_init(toku_uninstrumented, &external_mutex, nullptr); + struct timeval start, end; toku::frwlock x; x.init(&external_mutex); toku_mutex_lock(&external_mutex); @@ -340,8 +341,8 @@ void time_frwlock_prelocked(void) { void time_frwlock(void) __attribute__((__noinline__)); void time_frwlock(void) { toku_mutex_t external_mutex; - toku_mutex_init(&external_mutex, NULL); - struct timeval start,end; + toku_mutex_init(toku_uninstrumented, &external_mutex, nullptr); + struct timeval start, end; toku::frwlock x; x.init(&external_mutex); toku_mutex_lock(&external_mutex); diff --git a/storage/tokudb/PerconaFT/util/tests/threadpool-test.cc b/storage/tokudb/PerconaFT/util/tests/threadpool-test.cc index 3379507270d..83c142edc2d 100644 --- a/storage/tokudb/PerconaFT/util/tests/threadpool-test.cc +++ b/storage/tokudb/PerconaFT/util/tests/threadpool-test.cc @@ -67,10 +67,11 @@ struct my_threadpool { static void my_threadpool_init (struct my_threadpool *my_threadpool, int max_threads) { int r; - r = toku_thread_pool_create(&my_threadpool->threadpool, max_threads); assert(r == 0); + r = toku_thread_pool_create(&my_threadpool->threadpool, max_threads); + assert(r == 0); assert(my_threadpool != 0); - toku_mutex_init(&my_threadpool->mutex, 0); - toku_cond_init(&my_threadpool->wait, 0); + toku_mutex_init(toku_uninstrumented, &my_threadpool->mutex, nullptr); + toku_cond_init(toku_uninstrumented, &my_threadpool->wait, nullptr); my_threadpool->closed = 0; my_threadpool->counter = 0; } diff --git a/storage/tokudb/PerconaFT/util/threadpool.cc b/storage/tokudb/PerconaFT/util/threadpool.cc index 146cc63242a..6e0ccf05f93 100644 --- a/storage/tokudb/PerconaFT/util/threadpool.cc +++ b/storage/tokudb/PerconaFT/util/threadpool.cc @@ -48,6 +48,11 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "threadpool.h" +toku_instr_key *tpool_lock_mutex_key; +toku_instr_key *tp_thread_wait_key; +toku_instr_key *tp_pool_wait_free_key; +toku_instr_key *tp_internal_thread_key; + struct toku_thread { struct toku_thread_pool *pool; toku_pthread_t tid; @@ -84,8 +89,12 @@ toku_thread_create(struct toku_thread_pool *pool, struct toku_thread **toku_thre } else { memset(thread, 0, sizeof *thread); thread->pool = pool; - toku_cond_init(&thread->wait, nullptr); - r = toku_pthread_create(&thread->tid, nullptr, toku_thread_run_internal, thread); + toku_cond_init(*tp_thread_wait_key, &thread->wait, nullptr); + r = toku_pthread_create(*tp_internal_thread_key, + &thread->tid, + nullptr, + toku_thread_run_internal, + thread); if (r) { toku_cond_destroy(&thread->wait); toku_free(thread); @@ -105,11 +114,11 @@ toku_thread_run(struct toku_thread *thread, void *(*f)(void *arg), void *arg) { toku_thread_pool_unlock(thread->pool); } -static void -toku_thread_destroy(struct toku_thread *thread) { +static void toku_thread_destroy(struct toku_thread *thread) { int r; void *ret; - r = toku_pthread_join(thread->tid, &ret); invariant(r == 0 && ret == thread); + r = toku_pthread_join(thread->tid, &ret); + invariant(r == 0 && ret == thread); struct toku_thread_pool *pool = thread->pool; toku_thread_pool_lock(pool); toku_list_remove(&thread->free_link); @@ -147,20 +156,20 @@ toku_thread_run_internal(void *arg) { thread->f = nullptr; toku_list_push(&pool->free_threads, &thread->free_link); } - return arg; -} + return toku_pthread_done(arg); +} -int -toku_thread_pool_create(struct toku_thread_pool **pool_return, int max_threads) { +int toku_thread_pool_create(struct toku_thread_pool **pool_return, + int max_threads) { int r; struct toku_thread_pool *CALLOC(pool); if (pool == nullptr) { r = get_error_errno(); } else { - toku_mutex_init(&pool->lock, nullptr); + toku_mutex_init(*tpool_lock_mutex_key, &pool->lock, nullptr); toku_list_init(&pool->free_threads); toku_list_init(&pool->all_threads); - toku_cond_init(&pool->wait_free, nullptr); + toku_cond_init(*tp_pool_wait_free_key, &pool->wait_free, nullptr); pool->cur_threads = 0; pool->max_threads = max_threads; *pool_return = pool; diff --git a/storage/tokudb/ha_tokudb.cc b/storage/tokudb/ha_tokudb.cc index 3c83049835a..f4b44c395dd 100644 --- a/storage/tokudb/ha_tokudb.cc +++ b/storage/tokudb/ha_tokudb.cc @@ -31,6 +31,8 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #include "ha_tokudb.h" #include "sql_db.h" +pfs_key_t ha_tokudb_mutex_key; +pfs_key_t num_DBs_lock_key; #if TOKU_INCLUDE_EXTENDED_KEYS static inline uint get_ext_key_parts(const KEY *key) { @@ -187,13 +189,9 @@ const char* TOKUDB_SHARE::get_state_string(share_state_t state) { void* TOKUDB_SHARE::operator new(size_t sz) { return tokudb::memory::malloc(sz, MYF(MY_WME|MY_ZEROFILL|MY_FAE)); } -void TOKUDB_SHARE::operator delete(void* p) { - tokudb::memory::free(p); -} -TOKUDB_SHARE::TOKUDB_SHARE() : - _num_DBs_lock(), - _mutex() { -} +void TOKUDB_SHARE::operator delete(void* p) { tokudb::memory::free(p); } +TOKUDB_SHARE::TOKUDB_SHARE() + : _num_DBs_lock(num_DBs_lock_key), _mutex(ha_tokudb_mutex_key) {} void TOKUDB_SHARE::init(const char* table_name) { _use_count = 0; thr_lock_init(&_thr_lock); @@ -228,20 +226,15 @@ void TOKUDB_SHARE::destroy() { thr_lock_delete(&_thr_lock); TOKUDB_SHARE_DBUG_VOID_RETURN(); } -TOKUDB_SHARE* TOKUDB_SHARE::get_share( - const char* table_name, - TABLE_SHARE* table_share, - THR_LOCK_DATA* data, - bool create_new) { - - _open_tables_mutex.lock(); +TOKUDB_SHARE* TOKUDB_SHARE::get_share(const char* table_name, + TABLE_SHARE* table_share, + THR_LOCK_DATA* data, + bool create_new) { + mutex_t_lock(_open_tables_mutex); int error = 0; - uint length = (uint) strlen(table_name); - TOKUDB_SHARE* share = - (TOKUDB_SHARE*)my_hash_search( - &_open_tables, - (uchar*)table_name, - length); + uint length = (uint)strlen(table_name); + TOKUDB_SHARE* share = (TOKUDB_SHARE*)my_hash_search( + &_open_tables, (uchar*)table_name, length); TOKUDB_TRACE_FOR_FLAGS( TOKUDB_DEBUG_SHARE, @@ -276,28 +269,27 @@ TOKUDB_SHARE* TOKUDB_SHARE::get_share( thr_lock_data_init(&(share->_thr_lock), data, NULL); exit: - _open_tables_mutex.unlock(); + mutex_t_unlock(_open_tables_mutex); return share; } void TOKUDB_SHARE::drop_share(TOKUDB_SHARE* share) { - TOKUDB_TRACE_FOR_FLAGS( - TOKUDB_DEBUG_SHARE, - "share[%p]:file[%s]:state[%s]:use_count[%d]", - share, - share->_full_table_name.ptr(), - get_state_string(share->_state), - share->_use_count); - - _open_tables_mutex.lock(); + TOKUDB_TRACE_FOR_FLAGS(TOKUDB_DEBUG_SHARE, + "share[%p]:file[%s]:state[%s]:use_count[%d]", + share, + share->_full_table_name.ptr(), + get_state_string(share->_state), + share->_use_count); + + mutex_t_lock(_open_tables_mutex); my_hash_delete(&_open_tables, (uchar*)share); - _open_tables_mutex.unlock(); + mutex_t_unlock(_open_tables_mutex); } TOKUDB_SHARE::share_state_t TOKUDB_SHARE::addref() { TOKUDB_SHARE_TRACE_FOR_FLAGS((TOKUDB_DEBUG_ENTER & TOKUDB_DEBUG_SHARE), - "file[%s]:state[%s]:use_count[%d]", - _full_table_name.ptr(), - get_state_string(_state), - _use_count); + "file[%s]:state[%s]:use_count[%d]", + _full_table_name.ptr(), + get_state_string(_state), + _use_count); lock(); _use_count++; @@ -312,7 +304,7 @@ int TOKUDB_SHARE::release() { int error, result = 0; - _mutex.lock(); + mutex_t_lock(_mutex); assert_always(_use_count != 0); _use_count--; if (_use_count == 0 && _state == TOKUDB_SHARE::OPENED) { @@ -356,7 +348,7 @@ int TOKUDB_SHARE::release() { _state = TOKUDB_SHARE::CLOSED; } - _mutex.unlock(); + mutex_t_unlock(_mutex); TOKUDB_SHARE_DBUG_RETURN(result); } @@ -1195,8 +1187,10 @@ static int generate_row_for_put( ha_tokudb::ha_tokudb(handlerton * hton, TABLE_SHARE * table_arg):handler(hton, table_arg) { TOKUDB_HANDLER_DBUG_ENTER(""); share = NULL; - int_table_flags = HA_REC_NOT_IN_SEQ | HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS | HA_PRIMARY_KEY_IN_READ_INDEX | HA_PRIMARY_KEY_REQUIRED_FOR_POSITION | - HA_FILE_BASED | HA_AUTO_PART_KEY | HA_TABLE_SCAN_ON_INDEX | HA_CAN_WRITE_DURING_OPTIMIZE; + int_table_flags = HA_REC_NOT_IN_SEQ | HA_NULL_IN_KEY | HA_CAN_INDEX_BLOBS + | HA_PRIMARY_KEY_IN_READ_INDEX | HA_PRIMARY_KEY_REQUIRED_FOR_POSITION + | HA_FILE_BASED | HA_AUTO_PART_KEY | HA_TABLE_SCAN_ON_INDEX + | HA_CAN_WRITE_DURING_OPTIMIZE | HA_ONLINE_ANALYZE; alloc_ptr = NULL; rec_buff = NULL; rec_update_buff = NULL; @@ -3313,12 +3307,12 @@ void ha_tokudb::start_bulk_insert(ha_rows rows) { delay_updating_ai_metadata = true; ai_metadata_update_required = false; abort_loader = false; - - share->_num_DBs_lock.lock_read(); + + rwlock_t_lock_read(share->_num_DBs_lock); uint curr_num_DBs = table->s->keys + tokudb_test(hidden_primary_key); num_DBs_locked_in_bulk = true; lock_count = 0; - + if ((rows == 0 || rows > 1) && share->try_table_lock) { if (tokudb::sysvars::prelock_empty(thd) && may_table_be_empty(transaction) && @@ -4029,14 +4023,13 @@ int ha_tokudb::write_row(uchar * record) { // grab reader lock on numDBs_lock // if (!num_DBs_locked_in_bulk) { - share->_num_DBs_lock.lock_read(); + rwlock_t_lock_read(share->_num_DBs_lock); num_DBs_locked = true; - } - else { + } else { lock_count++; if (lock_count >= 2000) { share->_num_DBs_lock.unlock(); - share->_num_DBs_lock.lock_read(); + rwlock_t_lock_read(share->_num_DBs_lock); lock_count = 0; } } @@ -4206,7 +4199,7 @@ int ha_tokudb::update_row(const uchar * old_row, const uchar * new_row) { // bool num_DBs_locked = false; if (!num_DBs_locked_in_bulk) { - share->_num_DBs_lock.lock_read(); + rwlock_t_lock_read(share->_num_DBs_lock); num_DBs_locked = true; } curr_num_DBs = share->num_DBs; @@ -4346,7 +4339,7 @@ int ha_tokudb::delete_row(const uchar * record) { // bool num_DBs_locked = false; if (!num_DBs_locked_in_bulk) { - share->_num_DBs_lock.lock_read(); + rwlock_t_lock_read(share->_num_DBs_lock); num_DBs_locked = true; } curr_num_DBs = share->num_DBs; @@ -4637,6 +4630,9 @@ int ha_tokudb::index_init(uint keynr, bool sorted) { if (tokudb::sysvars::disable_prefetching(thd)) { cursor_flags |= DBC_DISABLE_PREFETCHING; } + if (lock.type == TL_READ_WITH_SHARED_LOCKS) { + cursor_flags |= DB_LOCKING_READ; + } if ((error = share->key_file[keynr]->cursor(share->key_file[keynr], transaction, &cursor, cursor_flags))) { @@ -6198,6 +6194,8 @@ int ha_tokudb::info(uint flag) { } if ((flag & HA_STATUS_CONST)) { stats.max_data_file_length = 9223372036854775807ULL; + } + if (flag & (HA_STATUS_VARIABLE | HA_STATUS_CONST)) { share->set_cardinality_counts_in_table(table); } @@ -6281,7 +6279,7 @@ int ha_tokudb::acquire_table_lock (DB_TXN* trans, TABLE_LOCK_TYPE lt) { TOKUDB_HANDLER_DBUG_ENTER("%p %s", trans, lt == lock_read ? "r" : "w"); int error = ENOSYS; if (!num_DBs_locked_in_bulk) { - share->_num_DBs_lock.lock_read(); + rwlock_t_lock_read(share->_num_DBs_lock); } uint curr_num_DBs = share->num_DBs; if (lt == lock_read) { @@ -6637,8 +6635,9 @@ THR_LOCK_DATA* *ha_tokudb::store_lock( if (sql_command == SQLCOM_CREATE_INDEX && tokudb::sysvars::create_index_online(thd)) { // hot indexing - share->_num_DBs_lock.lock_read(); - if (share->num_DBs == (table->s->keys + tokudb_test(hidden_primary_key))) { + rwlock_t_lock_read(share->_num_DBs_lock); + if (share->num_DBs == + (table->s->keys + tokudb_test(hidden_primary_key))) { lock_type = TL_WRITE_ALLOW_WRITE; } share->_num_DBs_lock.unlock(); @@ -7212,10 +7211,28 @@ int ha_tokudb::create( const tokudb::sysvars::row_format_t row_format = (tokudb::sysvars::row_format_t)form->s->option_struct->row_format; #else - const tokudb::sysvars::row_format_t row_format = - (create_info->used_fields & HA_CREATE_USED_ROW_FORMAT) - ? row_type_to_row_format(create_info->row_type) - : tokudb::sysvars::row_format(thd); + // TDB-76 : CREATE TABLE ... LIKE ... does not use source row_format on + // target table + // Original code would only use create_info->row_type if + // create_info->used_fields & HA_CREATE_USED_ROW_FORMAT was true. This + // would cause us to skip transferring the row_format for a table created + // via CREATE TABLE tn LIKE tn. We also take on more InnoDB like behavior + // and throw a warning if we get a row_format that we can't translate into + // a known TokuDB row_format. + tokudb::sysvars::row_format_t row_format = + tokudb::sysvars::row_format(thd); + + if ((create_info->used_fields & HA_CREATE_USED_ROW_FORMAT) || + create_info->row_type != ROW_TYPE_DEFAULT) { + row_format = row_type_to_row_format(create_info->row_type); + if (row_format == tokudb::sysvars::SRV_ROW_FORMAT_DEFAULT && + create_info->row_type != ROW_TYPE_DEFAULT) { + push_warning(thd, + Sql_condition::WARN_LEVEL_WARN, + ER_ILLEGAL_HA_CREATE_OPTION, + "TokuDB: invalid ROW_FORMAT specifier."); + } + } #endif const toku_compression_method compression_method = row_format_to_toku_compression_method(row_format); @@ -8099,8 +8116,8 @@ int ha_tokudb::tokudb_add_index( } } } - - share->_num_DBs_lock.lock_write(); + + rwlock_t_lock_write(share->_num_DBs_lock); rw_lock_taken = true; // // open all the DB files and set the appropriate variables in share @@ -8210,7 +8227,7 @@ int ha_tokudb::tokudb_add_index( goto cleanup; } - share->_num_DBs_lock.lock_write(); + rwlock_t_lock_write(share->_num_DBs_lock); error = indexer->close(indexer); share->_num_DBs_lock.unlock(); if (error) { @@ -8444,7 +8461,7 @@ cleanup: if (indexer != NULL) { sprintf(status_msg, "aborting creation of indexes."); thd_proc_info(thd, status_msg); - share->_num_DBs_lock.lock_write(); + rwlock_t_lock_write(share->_num_DBs_lock); indexer->abort(indexer); share->_num_DBs_lock.unlock(); } @@ -8493,10 +8510,10 @@ void ha_tokudb::restore_add_index( // // need to restore num_DBs, and we have to do it before we close the dictionaries - // so that there is not a window + // so that there is not a window // if (incremented_numDBs) { - share->_num_DBs_lock.lock_write(); + rwlock_t_lock_write(share->_num_DBs_lock); share->num_DBs--; } if (modified_DBs) { diff --git a/storage/tokudb/ha_tokudb.h b/storage/tokudb/ha_tokudb.h index 7476efe380f..c80be207005 100644 --- a/storage/tokudb/ha_tokudb.h +++ b/storage/tokudb/ha_tokudb.h @@ -318,18 +318,18 @@ inline int TOKUDB_SHARE::use_count() const { } inline void TOKUDB_SHARE::lock() const { TOKUDB_SHARE_DBUG_ENTER("file[%s]:state[%s]:use_count[%d]", - _full_table_name.ptr(), - get_state_string(_state), - _use_count); - _mutex.lock(); + _full_table_name.ptr(), + get_state_string(_state), + _use_count); + mutex_t_lock(_mutex); TOKUDB_SHARE_DBUG_VOID_RETURN(); } inline void TOKUDB_SHARE::unlock() const { TOKUDB_SHARE_DBUG_ENTER("file[%s]:state[%s]:use_count[%d]", - _full_table_name.ptr(), - get_state_string(_state), - _use_count); - _mutex.unlock(); + _full_table_name.ptr(), + get_state_string(_state), + _use_count); + mutex_t_unlock(_mutex); TOKUDB_SHARE_DBUG_VOID_RETURN(); } inline TOKUDB_SHARE::share_state_t TOKUDB_SHARE::state() const { diff --git a/storage/tokudb/ha_tokudb_update.cc b/storage/tokudb/ha_tokudb_update.cc index a6c72506448..2e56d4c6698 100644 --- a/storage/tokudb/ha_tokudb_update.cc +++ b/storage/tokudb/ha_tokudb_update.cc @@ -918,7 +918,7 @@ int ha_tokudb::send_update_message( marshall_update(update_message, lhs_item, rhs_item, table, share); } - share->_num_DBs_lock.lock_read(); + rwlock_t_lock_read(share->_num_DBs_lock); // hot index in progress if (share->num_DBs > table->s->keys + tokudb_test(hidden_primary_key)) { @@ -1108,7 +1108,7 @@ int ha_tokudb::send_upsert_message( marshall_update(update_message, lhs_item, rhs_item, table, share); } - share->_num_DBs_lock.lock_read(); + rwlock_t_lock_read(share->_num_DBs_lock); // hot index in progress if (share->num_DBs > table->s->keys + tokudb_test(hidden_primary_key)) { diff --git a/storage/tokudb/hatoku_cmp.cc b/storage/tokudb/hatoku_cmp.cc index ee57e064fbf..05a4b2da8c7 100644 --- a/storage/tokudb/hatoku_cmp.cc +++ b/storage/tokudb/hatoku_cmp.cc @@ -1983,6 +1983,7 @@ static uint32_t pack_desc_key_length_info(uchar* buf, KEY_AND_COL_INFO* kc_info, case (toku_type_fixstring): field_length = field->pack_length(); set_if_smaller(key_part_length, field_length); + // fallthrough case (toku_type_varbinary): case (toku_type_varstring): case (toku_type_blob): diff --git a/storage/tokudb/hatoku_defines.h b/storage/tokudb/hatoku_defines.h index a03f365d724..2f058797993 100644 --- a/storage/tokudb/hatoku_defines.h +++ b/storage/tokudb/hatoku_defines.h @@ -168,6 +168,14 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #define HA_CAN_WRITE_DURING_OPTIMIZE 0 #endif +#if !defined(HA_ONLINE_ANALYZE) +#define HA_ONLINE_ANALYZE 0 +#endif + +#if !defined(MY_ATTRIBUTE) +#define MY_ATTRIBUTE(A) __attribute__(A) +#endif + #if !defined(HA_OPTION_CREATE_FROM_ENGINE) #define HA_OPTION_CREATE_FROM_ENGINE 0 #endif @@ -248,4 +256,22 @@ inline uint tokudb_uint3korr(const uchar *a) { return uint3korr(b); } -#endif // _HATOKU_DEFINES_H +typedef unsigned int pfs_key_t; + +#if defined(HAVE_PSI_MUTEX_INTERFACE) +#define mutex_t_lock(M) M.lock(__FILE__, __LINE__) +#define mutex_t_unlock(M) M.unlock(__FILE__, __LINE__) +#else // HAVE_PSI_MUTEX_INTERFACE +#define mutex_t_lock(M) M.lock() +#define mutex_t_unlock(M) M.unlock() +#endif // HAVE_PSI_MUTEX_INTERFACE + +#if defined(HAVE_PSI_RWLOCK_INTERFACE) +#define rwlock_t_lock_read(M) M.lock_read(__FILE__, __LINE__) +#define rwlock_t_lock_write(M) M.lock_write(__FILE__, __LINE__) +#else // HAVE_PSI_RWLOCK_INTERFACE +#define rwlock_t_lock_read(M) M.lock_read() +#define rwlock_t_lock_write(M) M.lock_write() +#endif // HAVE_PSI_RWLOCK_INTERFACE + +#endif // _HATOKU_DEFINES_H diff --git a/storage/tokudb/hatoku_hton.cc b/storage/tokudb/hatoku_hton.cc index 599948e03f8..cee8575eebb 100644 --- a/storage/tokudb/hatoku_hton.cc +++ b/storage/tokudb/hatoku_hton.cc @@ -28,6 +28,17 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. #define TOKU_METADB_NAME "tokudb_meta" +static pfs_key_t tokudb_map_mutex_key; + +static PSI_mutex_info all_tokudb_mutexes[] = { + {&tokudb_map_mutex_key, "tokudb_map_mutex", 0}, + {&ha_tokudb_mutex_key, "ha_tokudb_mutex", 0}, +}; + +static PSI_rwlock_info all_tokudb_rwlocks[] = { + {&num_DBs_lock_key, "num_DBs_lock", 0}, +}; + typedef struct savepoint_info { DB_TXN* txn; tokudb_trx_data* trx; @@ -109,8 +120,8 @@ handlerton* tokudb_hton; const char* ha_tokudb_ext = ".tokudb"; DB_ENV* db_env; -#if TOKU_THDVAR_MEMALLOC_BUG static tokudb::thread::mutex_t tokudb_map_mutex; +#if TOKU_THDVAR_MEMALLOC_BUG static TREE tokudb_map; struct tokudb_map_pair { THD* thd; @@ -212,6 +223,10 @@ extern "C" { // use constructor and destructor functions to create and destroy // the lock before and after main(), respectively. int tokudb_hton_initialized; + +// tokudb_hton_initialized_lock can not be instrumented as it must be +// initialized before mysql_mutex_register() call to protect +// some globals from race condition. tokudb::thread::rwlock_t tokudb_hton_initialized_lock; static SHOW_VAR *toku_global_status_variables = NULL; @@ -267,10 +282,23 @@ static int tokudb_init_func(void *p) { int r; // 3938: lock the handlerton's initialized status flag for writing - tokudb_hton_initialized_lock.lock_write(); + rwlock_t_lock_write(tokudb_hton_initialized_lock); + +#ifdef HAVE_PSI_INTERFACE + /* Register TokuDB mutex keys with MySQL performance schema */ + int count; + + count = array_elements(all_tokudb_mutexes); + mysql_mutex_register("tokudb", all_tokudb_mutexes, count); + + count = array_elements(all_tokudb_rwlocks); + mysql_rwlock_register("tokudb", all_tokudb_rwlocks, count); + + tokudb_map_mutex.reinit(tokudb_map_mutex_key); +#endif /* HAVE_PSI_INTERFACE */ db_env = NULL; - tokudb_hton = (handlerton *) p; + tokudb_hton = (handlerton*)p; if (tokudb::sysvars::check_jemalloc) { typedef int (*mallctl_type)( @@ -668,7 +696,7 @@ int tokudb_end(handlerton* hton, ha_panic_function type) { // initialized. grab a writer lock for the duration of the // call, so we can drop the flag and destroy the mutexes // in isolation. - tokudb_hton_initialized_lock.lock_write(); + rwlock_t_lock_write(tokudb_hton_initialized_lock); assert_always(tokudb_hton_initialized); tokudb::background::destroy(); @@ -748,16 +776,16 @@ static int tokudb_close_connection(handlerton* hton, THD* thd) { } tokudb::memory::free(trx); #if TOKU_THDVAR_MEMALLOC_BUG - tokudb_map_mutex.lock(); - struct tokudb_map_pair key = { thd, NULL }; + mutex_t_lock(tokudb_map_mutex); + struct tokudb_map_pair key = {thd, NULL}; struct tokudb_map_pair* found_key = - (struct tokudb_map_pair*) tree_search(&tokudb_map, &key, NULL); + (struct tokudb_map_pair*)tree_search(&tokudb_map, &key, NULL); if (found_key) { tokudb::memory::free(found_key->last_lock_timeout); tree_delete(&tokudb_map, found_key, sizeof(*found_key), NULL); } - tokudb_map_mutex.unlock(); + mutex_t_unlock(tokudb_map_mutex); #endif return error; } @@ -1718,12 +1746,12 @@ static void tokudb_lock_timeout_callback( tokudb::memory::strdup(log_str.c_ptr(), MY_FAE); tokudb::sysvars::set_last_lock_timeout(thd, new_lock_timeout); #if TOKU_THDVAR_MEMALLOC_BUG - tokudb_map_mutex.lock(); - struct tokudb_map_pair old_key = { thd, old_lock_timeout }; + mutex_t_lock(tokudb_map_mutex); + struct tokudb_map_pair old_key = {thd, old_lock_timeout}; tree_delete(&tokudb_map, &old_key, sizeof old_key, NULL); - struct tokudb_map_pair new_key = { thd, new_lock_timeout }; + struct tokudb_map_pair new_key = {thd, new_lock_timeout}; tree_insert(&tokudb_map, &new_key, sizeof new_key, NULL); - tokudb_map_mutex.unlock(); + mutex_t_unlock(tokudb_map_mutex); #endif tokudb::memory::free(old_lock_timeout); } diff --git a/storage/tokudb/hatoku_hton.h b/storage/tokudb/hatoku_hton.h index d126ff4339f..80e13fa9b0c 100644 --- a/storage/tokudb/hatoku_hton.h +++ b/storage/tokudb/hatoku_hton.h @@ -39,6 +39,9 @@ extern handlerton* tokudb_hton; extern DB_ENV* db_env; +extern pfs_key_t ha_tokudb_mutex_key; +extern pfs_key_t num_DBs_lock_key; + inline tokudb::sysvars::row_format_t toku_compression_method_to_row_format( toku_compression_method method) { @@ -180,9 +183,7 @@ inline bool tokudb_killed_thd_callback(void *extra, uint64_t deleted_rows) { return thd_kill_level(thd) != 0; } - extern HASH tokudb_open_tables; -extern tokudb::thread::mutex_t tokudb_mutex; extern const char* tokudb_hton_name; extern int tokudb_hton_initialized; extern tokudb::thread::rwlock_t tokudb_hton_initialized_lock; diff --git a/storage/tokudb/mysql-test/tokudb/disabled.def b/storage/tokudb/mysql-test/tokudb/disabled.def index 8893dfabdc6..89f6992d26d 100644 --- a/storage/tokudb/mysql-test/tokudb/disabled.def +++ b/storage/tokudb/mysql-test/tokudb/disabled.def @@ -29,5 +29,6 @@ cluster_key_part: engine options on partitioned tables i_s_tokudb_lock_waits_released: unstable, race conditions i_s_tokudb_locks_released: unstable, race conditions row_format: n/a +nonflushing_analyze_debug: Freezes in MariaDB 10.0 tokudb.change_column_all_1000_1: We are too lazy to fix this properly tokudb.change_column_all_1000_10: We are too lazy to fix this properly diff --git a/storage/tokudb/mysql-test/tokudb/r/card_scale_percent.result b/storage/tokudb/mysql-test/tokudb/r/card_scale_percent.result index cfd7e38179c..981433fac91 100644 --- a/storage/tokudb/mysql-test/tokudb/r/card_scale_percent.result +++ b/storage/tokudb/mysql-test/tokudb/r/card_scale_percent.result @@ -1,7 +1,7 @@ -set global tokudb_cardinality_scale_percent = 10; analyze table tt; Table Op Msg_type Msg_text test.tt analyze status OK +set global tokudb_cardinality_scale_percent = 10; show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment tt 0 PRIMARY 1 a A 4000 NULL NULL BTREE @@ -9,9 +9,6 @@ tt 1 b 1 b A 4000 NULL NULL YES BTREE tt 1 c 1 c A 4000 NULL NULL YES BTREE tt 1 d 1 d A 4000 NULL NULL YES BTREE set global tokudb_cardinality_scale_percent = 50; -analyze table tt; -Table Op Msg_type Msg_text -test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment tt 0 PRIMARY 1 a A 4000 NULL NULL BTREE @@ -19,9 +16,6 @@ tt 1 b 1 b A 4000 NULL NULL YES BTREE tt 1 c 1 c A 4000 NULL NULL YES BTREE tt 1 d 1 d A 2000 NULL NULL YES BTREE set global tokudb_cardinality_scale_percent = 100; -analyze table tt; -Table Op Msg_type Msg_text -test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment tt 0 PRIMARY 1 a A 4000 NULL NULL BTREE @@ -31,9 +25,6 @@ tt 1 d 1 d A 1000 NULL NULL YES BTREE set global tokudb_cardinality_scale_percent = 200; Warnings: Warning 1292 Truncated incorrect tokudb_cardinality_scale_percent value: '200' -analyze table tt; -Table Op Msg_type Msg_text -test.tt analyze status OK show indexes from tt; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment tt 0 PRIMARY 1 a A 4000 NULL NULL BTREE diff --git a/storage/tokudb/mysql-test/tokudb/r/locking-read-repeatable-read-1.result b/storage/tokudb/mysql-test/tokudb/r/locking-read-repeatable-read-1.result new file mode 100644 index 00000000000..433b5baf18b --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb/r/locking-read-repeatable-read-1.result @@ -0,0 +1,16 @@ +create table t (a int primary key, b int) ENGINE=TokuDB; +insert into t values (1,0); +set session transaction isolation level repeatable read; +begin; +select * from t where a=1 lock in share mode; +a b +1 0 +connect conn1,localhost,root; +set session transaction isolation level repeatable read; +begin; +update t set b=b+1 where a=1; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +connection default; +commit; +disconnect conn1; +drop table t; diff --git a/storage/tokudb/mysql-test/tokudb/r/locking-read-repeatable-read-2.result b/storage/tokudb/mysql-test/tokudb/r/locking-read-repeatable-read-2.result new file mode 100644 index 00000000000..79e886a8682 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb/r/locking-read-repeatable-read-2.result @@ -0,0 +1,20 @@ +create table t (a int primary key, b int) ENGINE=TokuDB; +insert into t values (1,0); +insert into t values (2,1); +insert into t values (3,2); +set session transaction isolation level repeatable read; +begin; +select * from t lock in share mode; +a b +1 0 +2 1 +3 2 +connect conn1,localhost,root; +set session transaction isolation level repeatable read; +begin; +update t set b=b+1 where a=2; +ERROR HY000: Lock wait timeout exceeded; try restarting transaction +connection default; +commit; +disconnect conn1; +drop table t; diff --git a/storage/tokudb/mysql-test/tokudb/r/nonflushing_analyze_debug.result b/storage/tokudb/mysql-test/tokudb/r/nonflushing_analyze_debug.result new file mode 100644 index 00000000000..e8f51edee04 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb/r/nonflushing_analyze_debug.result @@ -0,0 +1,19 @@ +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=TokuDB; +INSERT INTO t1 VALUES (1), (2), (3); +SET DEBUG_SYNC="handler_ha_index_next_end SIGNAL idx_scan_in_progress WAIT_FOR finish_scan"; +SELECT * FROM t1; +SET DEBUG_SYNC="now WAIT_FOR idx_scan_in_progress"; +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +SELECT * FROM t1; +a +1 +2 +3 +SET DEBUG_SYNC="now SIGNAL finish_scan"; +a +1 +2 +3 +DROP TABLE t1; diff --git a/storage/tokudb/mysql-test/tokudb/r/row_format.result b/storage/tokudb/mysql-test/tokudb/r/row_format.result index cb669148445..15d4f9fe12a 100644 --- a/storage/tokudb/mysql-test/tokudb/r/row_format.result +++ b/storage/tokudb/mysql-test/tokudb/r/row_format.result @@ -1,4 +1,6 @@ CREATE TABLE tokudb_row_format_test_1 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_DEFAULT; +Warnings: +Warning 1478 TokuDB: invalid ROW_FORMAT specifier. CREATE TABLE tokudb_row_format_test_2 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_FAST; CREATE TABLE tokudb_row_format_test_3 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_SMALL; CREATE TABLE tokudb_row_format_test_4 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_UNCOMPRESSED; @@ -6,6 +8,41 @@ CREATE TABLE tokudb_row_format_test_5 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_ZL CREATE TABLE tokudb_row_format_test_6 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_LZMA; CREATE TABLE tokudb_row_format_test_7 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_QUICKLZ; CREATE TABLE tokudb_row_format_test_8 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_SNAPPY; +CREATE TABLE tdb76_1 LIKE tokudb_row_format_test_1; +CREATE TABLE tdb76_2 LIKE tokudb_row_format_test_2; +CREATE TABLE tdb76_3 LIKE tokudb_row_format_test_3; +CREATE TABLE tdb76_4 LIKE tokudb_row_format_test_4; +CREATE TABLE tdb76_5 LIKE tokudb_row_format_test_5; +CREATE TABLE tdb76_6 LIKE tokudb_row_format_test_6; +CREATE TABLE tdb76_7 LIKE tokudb_row_format_test_7; +CREATE TABLE tdb76_8 LIKE tokudb_row_format_test_8; +CREATE TABLE tdb76_compact(a INT) ENGINE=TokuDB ROW_FORMAT=COMPACT; +Warnings: +Warning 1478 TokuDB: invalid ROW_FORMAT specifier. +CREATE TABLE tdb76_redundant(a INT) ENGINE=TokuDB ROW_FORMAT=REDUNDANT; +Warnings: +Warning 1478 TokuDB: invalid ROW_FORMAT specifier. +CREATE TABLE tdb76_dynamic(a INT) ENGINE=TokuDB ROW_FORMAT=DYNAMIC; +Warnings: +Warning 1478 TokuDB: invalid ROW_FORMAT specifier. +CREATE TABLE tdb76_compressed(a INT) ENGINE=TokuDB ROW_FORMAT=COMPRESSED; +Warnings: +Warning 1478 TokuDB: invalid ROW_FORMAT specifier. +SELECT table_name, row_format, engine FROM information_schema.tables WHERE table_name like 'tdb76_%' ORDER BY table_name; +table_name row_format engine +tdb76_1 tokudb_zlib TokuDB +tdb76_2 tokudb_quicklz TokuDB +tdb76_3 tokudb_lzma TokuDB +tdb76_4 tokudb_uncompressed TokuDB +tdb76_5 tokudb_zlib TokuDB +tdb76_6 tokudb_lzma TokuDB +tdb76_7 tokudb_quicklz TokuDB +tdb76_8 tokudb_snappy TokuDB +tdb76_compact tokudb_zlib TokuDB +tdb76_compressed tokudb_zlib TokuDB +tdb76_dynamic tokudb_zlib TokuDB +tdb76_redundant tokudb_zlib TokuDB +DROP TABLE tdb76_1, tdb76_2, tdb76_3, tdb76_4, tdb76_5, tdb76_6, tdb76_7, tdb76_8, tdb76_compact, tdb76_redundant, tdb76_dynamic, tdb76_compressed; SELECT table_name, row_format, engine FROM information_schema.tables WHERE table_name like 'tokudb_row_format_test%' ORDER BY table_name; table_name row_format engine tokudb_row_format_test_1 tokudb_zlib TokuDB @@ -45,6 +82,8 @@ SELECT table_name, row_format, engine FROM information_schema.tables WHERE table table_name row_format engine tokudb_row_format_test_1 tokudb_lzma TokuDB ALTER TABLE tokudb_row_format_test_1 ENGINE=TokuDB ROW_FORMAT=TOKUDB_DEFAULT; +Warnings: +Warning 1478 TokuDB: invalid ROW_FORMAT specifier. SELECT table_name, row_format, engine FROM information_schema.tables WHERE table_name = 'tokudb_row_format_test_1'; table_name row_format engine tokudb_row_format_test_1 tokudb_zlib TokuDB diff --git a/storage/tokudb/mysql-test/tokudb/t/card_scale_percent.test b/storage/tokudb/mysql-test/tokudb/t/card_scale_percent.test index 47f1eb37989..75c53611308 100644 --- a/storage/tokudb/mysql-test/tokudb/t/card_scale_percent.test +++ b/storage/tokudb/mysql-test/tokudb/t/card_scale_percent.test @@ -30,20 +30,18 @@ set session tokudb_analyze_throttle=0; -- enable_query_log -set global tokudb_cardinality_scale_percent = 10; analyze table tt; + +set global tokudb_cardinality_scale_percent = 10; show indexes from tt; set global tokudb_cardinality_scale_percent = 50; -analyze table tt; show indexes from tt; set global tokudb_cardinality_scale_percent = 100; -analyze table tt; show indexes from tt; set global tokudb_cardinality_scale_percent = 200; -analyze table tt; show indexes from tt; -- disable_query_log diff --git a/storage/tokudb/mysql-test/tokudb/t/locking-read-repeatable-read-1.test b/storage/tokudb/mysql-test/tokudb/t/locking-read-repeatable-read-1.test new file mode 100644 index 00000000000..c5ef0f0703e --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb/t/locking-read-repeatable-read-1.test @@ -0,0 +1,23 @@ +source include/have_tokudb.inc; +source include/count_sessions.inc; +create table t (a int primary key, b int) ENGINE=TokuDB; +insert into t values (1,0); +set session transaction isolation level repeatable read; +begin; +# t1 select in share mode +select * from t where a=1 lock in share mode; +# t2 update +connect(conn1,localhost,root); +set session transaction isolation level repeatable read; +begin; +# t2 select for update, should hang until t1 commits +send update t set b=b+1 where a=1; +--error ER_LOCK_WAIT_TIMEOUT +reap; +# t2 update +connection default; +commit; +disconnect conn1; +drop table t; + +source include/wait_until_count_sessions.inc; diff --git a/storage/tokudb/mysql-test/tokudb/t/locking-read-repeatable-read-2.test b/storage/tokudb/mysql-test/tokudb/t/locking-read-repeatable-read-2.test new file mode 100644 index 00000000000..20a4549c45f --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb/t/locking-read-repeatable-read-2.test @@ -0,0 +1,29 @@ +#the difference of this test from locking-read-repeatable-read-1 +#is that this test is on range query(gap lock) which actually +#examines a different patch + +source include/have_tokudb.inc; +source include/count_sessions.inc; +create table t (a int primary key, b int) ENGINE=TokuDB; +insert into t values (1,0); +insert into t values (2,1); +insert into t values (3,2); +set session transaction isolation level repeatable read; +begin; +# t1 select in share mode +select * from t lock in share mode; +# t2 update +connect(conn1,localhost,root); +set session transaction isolation level repeatable read; +begin; +# t2 select for update, should hang until t1 commits +send update t set b=b+1 where a=2; +--error ER_LOCK_WAIT_TIMEOUT +reap; +# t2 update +connection default; +commit; +disconnect conn1; +drop table t; + +source include/wait_until_count_sessions.inc; diff --git a/storage/tokudb/mysql-test/tokudb/t/nonflushing_analyze_debug.test b/storage/tokudb/mysql-test/tokudb/t/nonflushing_analyze_debug.test new file mode 100644 index 00000000000..0c4c01b3dc0 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb/t/nonflushing_analyze_debug.test @@ -0,0 +1,10 @@ +--source include/have_debug_sync.inc +--source include/have_tokudb.inc + +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=TokuDB; +INSERT INTO t1 VALUES (1), (2), (3); + +--let $percona_nonflushing_analyze_table= t1 +--source include/percona_nonflushing_analyze_debug.inc + +DROP TABLE t1; diff --git a/storage/tokudb/mysql-test/tokudb/t/row_format.test b/storage/tokudb/mysql-test/tokudb/t/row_format.test index 6533f8c06be..9c5c6e6403e 100644 --- a/storage/tokudb/mysql-test/tokudb/t/row_format.test +++ b/storage/tokudb/mysql-test/tokudb/t/row_format.test @@ -12,6 +12,27 @@ CREATE TABLE tokudb_row_format_test_6 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_LZ CREATE TABLE tokudb_row_format_test_7 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_QUICKLZ; CREATE TABLE tokudb_row_format_test_8 (a INT) ENGINE=TokuDB ROW_FORMAT=TOKUDB_SNAPPY; +# TDB-76 : CREATE TABLE ... LIKE ... does not use source row_format on target table +CREATE TABLE tdb76_1 LIKE tokudb_row_format_test_1; +CREATE TABLE tdb76_2 LIKE tokudb_row_format_test_2; +CREATE TABLE tdb76_3 LIKE tokudb_row_format_test_3; +CREATE TABLE tdb76_4 LIKE tokudb_row_format_test_4; +CREATE TABLE tdb76_5 LIKE tokudb_row_format_test_5; +CREATE TABLE tdb76_6 LIKE tokudb_row_format_test_6; +CREATE TABLE tdb76_7 LIKE tokudb_row_format_test_7; +CREATE TABLE tdb76_8 LIKE tokudb_row_format_test_8; + +CREATE TABLE tdb76_compact(a INT) ENGINE=TokuDB ROW_FORMAT=COMPACT; +CREATE TABLE tdb76_redundant(a INT) ENGINE=TokuDB ROW_FORMAT=REDUNDANT; +CREATE TABLE tdb76_dynamic(a INT) ENGINE=TokuDB ROW_FORMAT=DYNAMIC; +CREATE TABLE tdb76_compressed(a INT) ENGINE=TokuDB ROW_FORMAT=COMPRESSED; + +SELECT table_name, row_format, engine FROM information_schema.tables WHERE table_name like 'tdb76_%' ORDER BY table_name; + +DROP TABLE tdb76_1, tdb76_2, tdb76_3, tdb76_4, tdb76_5, tdb76_6, tdb76_7, tdb76_8, tdb76_compact, tdb76_redundant, tdb76_dynamic, tdb76_compressed; + + + SELECT table_name, row_format, engine FROM information_schema.tables WHERE table_name like 'tokudb_row_format_test%' ORDER BY table_name; ALTER TABLE tokudb_row_format_test_1 ENGINE=TokuDB ROW_FORMAT=TOKUDB_FAST; diff --git a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1_pick.result b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1_pick.result index 5ba5da21789..caaa963c325 100644 --- a/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1_pick.result +++ b/storage/tokudb/mysql-test/tokudb_bugs/r/db756_card_part_hash_1_pick.result @@ -17,5 +17,5 @@ test.t analyze status OK show indexes from t; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment t 0 PRIMARY 1 id A 7 NULL NULL BTREE -t 1 x 1 x A 3 NULL NULL YES BTREE +t 1 x 1 x A 7 NULL NULL YES BTREE drop table t; diff --git a/storage/tokudb/mysql-test/tokudb_parts/disabled.def b/storage/tokudb/mysql-test/tokudb_parts/disabled.def index 3252a463176..17a8ddcc12e 100644 --- a/storage/tokudb/mysql-test/tokudb_parts/disabled.def +++ b/storage/tokudb/mysql-test/tokudb_parts/disabled.def @@ -7,3 +7,4 @@ partition_max_sub_parts_key_list_tokudb: 5.6 test not merged yet partition_max_sub_parts_key_range_tokudb: 5.6 test not merged yet partition_max_sub_parts_list_tokudb: 5.6 test not merged yet partition_max_sub_parts_range_tokudb: 5.6 test not merged yet +nonflushing_analyze_debug: Freezes in MariaDB 10.0 diff --git a/storage/tokudb/mysql-test/tokudb_parts/r/nonflushing_analyze_debug.result b/storage/tokudb/mysql-test/tokudb_parts/r/nonflushing_analyze_debug.result new file mode 100644 index 00000000000..5a7bfb369df --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_parts/r/nonflushing_analyze_debug.result @@ -0,0 +1,50 @@ +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=TokuDB +PARTITION BY RANGE (a) ( +PARTITION p0 VALUES LESS THAN (3), +PARTITION p1 VALUES LESS THAN (10)); +INSERT INTO t1 VALUES (1), (2), (3), (4); +SET DEBUG_SYNC="handler_ha_index_next_end SIGNAL idx_scan_in_progress WAIT_FOR finish_scan"; +SELECT * FROM t1; +SET DEBUG_SYNC="now WAIT_FOR idx_scan_in_progress"; +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +SELECT * FROM t1; +a +1 +2 +3 +4 +SET DEBUG_SYNC="now SIGNAL finish_scan"; +a +1 +2 +3 +4 +DROP TABLE t1; +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=TokuDB +PARTITION BY RANGE (a) +SUBPARTITION BY HASH (A) +SUBPARTITIONS 2 ( +PARTITION p0 VALUES LESS THAN (3), +PARTITION p1 VALUES LESS THAN (10)); +INSERT INTO t2 VALUES (1), (2), (3), (4); +SET DEBUG_SYNC="handler_ha_index_next_end SIGNAL idx_scan_in_progress WAIT_FOR finish_scan"; +SELECT * FROM t2; +SET DEBUG_SYNC="now WAIT_FOR idx_scan_in_progress"; +ANALYZE TABLE t2; +Table Op Msg_type Msg_text +test.t2 analyze status OK +SELECT * FROM t2; +a +2 +1 +4 +3 +SET DEBUG_SYNC="now SIGNAL finish_scan"; +a +2 +1 +4 +3 +DROP TABLE t2; diff --git a/storage/tokudb/mysql-test/tokudb_parts/t/nonflushing_analyze_debug.test b/storage/tokudb/mysql-test/tokudb_parts/t/nonflushing_analyze_debug.test new file mode 100644 index 00000000000..c99206acfe3 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_parts/t/nonflushing_analyze_debug.test @@ -0,0 +1,29 @@ +--source include/have_debug_sync.inc +--source include/have_tokudb.inc +--source include/have_partition.inc + +CREATE TABLE t1 (a INT PRIMARY KEY) ENGINE=TokuDB + PARTITION BY RANGE (a) ( + PARTITION p0 VALUES LESS THAN (3), + PARTITION p1 VALUES LESS THAN (10)); + +INSERT INTO t1 VALUES (1), (2), (3), (4); + +--let $percona_nonflushing_analyze_table= t1 +--source include/percona_nonflushing_analyze_debug.inc + +DROP TABLE t1; + +CREATE TABLE t2 (a INT PRIMARY KEY) ENGINE=TokuDB + PARTITION BY RANGE (a) + SUBPARTITION BY HASH (A) + SUBPARTITIONS 2 ( + PARTITION p0 VALUES LESS THAN (3), + PARTITION p1 VALUES LESS THAN (10)); + +INSERT INTO t2 VALUES (1), (2), (3), (4); + +--let $percona_nonflushing_analyze_table= t2 +--source include/percona_nonflushing_analyze_debug.inc + +DROP TABLE t2; diff --git a/storage/tokudb/mysql-test/tokudb_perfschema/r/crash_tokudb.result b/storage/tokudb/mysql-test/tokudb_perfschema/r/crash_tokudb.result new file mode 100644 index 00000000000..189d6bef14e --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_perfschema/r/crash_tokudb.result @@ -0,0 +1,30 @@ +SELECT COUNT(*) > 0 FROM performance_schema.setup_consumers +WHERE ENABLED = "NO"; +COUNT(*) > 0 +0 +SELECT COUNT(*) > 0 FROM performance_schema.setup_instruments +WHERE NAME LIKE "%/fti/%" AND (ENABLED = 'NO' OR TIMED = "NO"); +COUNT(*) > 0 +0 +CREATE TABLE t(a INT AUTO_INCREMENT PRIMARY KEY, b INT) ENGINE=TokuDB; +INSERT INTO t (b) VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10), +(1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +INSERT INTO t (b) SELECT b FROM t; +UPDATE t SET b = 11 WHERE b = 10; +DELETE FROM t WHERE b = 1; +ALTER TABLE t ADD COLUMN c CHAR(10) default NULL; +TRUNCATE TABLE t; +RENAME TABLE t TO t1; +RENAME TABLE t1 TO t; +SELECT COUNT(*) > 0 FROM t; +COUNT(*) > 0 +0 +DROP TABLE t; diff --git a/storage/tokudb/mysql-test/tokudb_perfschema/r/start_server_tokudb.result b/storage/tokudb/mysql-test/tokudb_perfschema/r/start_server_tokudb.result new file mode 100644 index 00000000000..2e220916ec3 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_perfschema/r/start_server_tokudb.result @@ -0,0 +1,114 @@ +show databases; +Database +information_schema +mtr +mysql +performance_schema +test +select count(*) from performance_schema.performance_timers; +count(*) +5 +select count(*) from performance_schema.setup_consumers; +count(*) +12 +select count(*) > 3 from performance_schema.setup_instruments; +count(*) > 3 +1 +select count(*) from performance_schema.setup_timers; +count(*) +4 +select * from performance_schema.accounts; +select * from performance_schema.cond_instances; +select * from performance_schema.events_stages_current; +select * from performance_schema.events_stages_history; +select * from performance_schema.events_stages_history_long; +select * from performance_schema.events_stages_summary_by_account_by_event_name; +select * from performance_schema.events_stages_summary_by_host_by_event_name; +select * from performance_schema.events_stages_summary_by_thread_by_event_name; +select * from performance_schema.events_stages_summary_by_user_by_event_name; +select * from performance_schema.events_stages_summary_global_by_event_name; +select * from performance_schema.events_statements_current; +select * from performance_schema.events_statements_history; +select * from performance_schema.events_statements_history_long; +select * from performance_schema.events_statements_summary_by_account_by_event_name; +select * from performance_schema.events_statements_summary_by_digest; +select * from performance_schema.events_statements_summary_by_host_by_event_name; +select * from performance_schema.events_statements_summary_by_thread_by_event_name; +select * from performance_schema.events_statements_summary_by_user_by_event_name; +select * from performance_schema.events_statements_summary_global_by_event_name; +select * from performance_schema.events_waits_current; +select * from performance_schema.events_waits_history; +select * from performance_schema.events_waits_history_long; +select * from performance_schema.events_waits_summary_by_account_by_event_name; +select * from performance_schema.events_waits_summary_by_host_by_event_name; +select * from performance_schema.events_waits_summary_by_instance; +select * from performance_schema.events_waits_summary_by_thread_by_event_name; +select * from performance_schema.events_waits_summary_by_user_by_event_name; +select * from performance_schema.events_waits_summary_global_by_event_name; +select * from performance_schema.file_instances; +select * from performance_schema.file_summary_by_event_name; +select * from performance_schema.file_summary_by_instance; +select * from performance_schema.host_cache; +select * from performance_schema.hosts; +select * from performance_schema.mutex_instances; +select * from performance_schema.objects_summary_global_by_type; +select * from performance_schema.performance_timers; +select * from performance_schema.rwlock_instances; +select * from performance_schema.session_account_connect_attrs; +select * from performance_schema.session_connect_attrs; +select * from performance_schema.setup_actors; +select * from performance_schema.setup_consumers; +select * from performance_schema.setup_instruments; +select * from performance_schema.setup_objects; +select * from performance_schema.setup_timers; +select * from performance_schema.socket_instances; +select * from performance_schema.socket_summary_by_instance; +select * from performance_schema.socket_summary_by_event_name; +select * from performance_schema.table_io_waits_summary_by_index_usage; +select * from performance_schema.table_io_waits_summary_by_table; +select * from performance_schema.table_lock_waits_summary_by_table; +select * from performance_schema.threads; +select * from performance_schema.users; +show variables where +`Variable_name` != "performance_schema_max_statement_classes" and +`Variable_name` like "performance_schema%"; +Variable_name Value +performance_schema ON +performance_schema_accounts_size 100 +performance_schema_digests_size 200 +performance_schema_events_stages_history_long_size 1000 +performance_schema_events_stages_history_size 10 +performance_schema_events_statements_history_long_size 1000 +performance_schema_events_statements_history_size 10 +performance_schema_events_waits_history_long_size 10000 +performance_schema_events_waits_history_size 10 +performance_schema_hosts_size 100 +performance_schema_max_cond_classes 80 +performance_schema_max_cond_instances 1000 +performance_schema_max_digest_length 1024 +performance_schema_max_file_classes 50 +performance_schema_max_file_handles 32768 +performance_schema_max_file_instances 10000 +performance_schema_max_mutex_classes 200 +performance_schema_max_mutex_instances 5000 +performance_schema_max_rwlock_classes 40 +performance_schema_max_rwlock_instances 5000 +performance_schema_max_socket_classes 10 +performance_schema_max_socket_instances 1000 +performance_schema_max_stage_classes 150 +performance_schema_max_table_handles 1000 +performance_schema_max_table_instances 500 +performance_schema_max_thread_classes 50 +performance_schema_max_thread_instances 200 +performance_schema_session_connect_attrs_size 2048 +performance_schema_setup_actors_size 100 +performance_schema_setup_objects_size 100 +performance_schema_users_size 100 +show engine PERFORMANCE_SCHEMA status; +show status like "performance_schema%"; +SELECT COUNT(NAME) > 0 FROM performance_schema.setup_instruments WHERE NAME LIKE "%/fti/%"; +COUNT(NAME) > 0 +1 +SELECT COUNT(NAME) > 0 FROM performance_schema.threads WHERE NAME LIKE "%kibbutz%"; +COUNT(NAME) > 0 +1 diff --git a/storage/tokudb/mysql-test/tokudb_perfschema/t/crash_tokudb.test b/storage/tokudb/mysql-test/tokudb_perfschema/t/crash_tokudb.test new file mode 100644 index 00000000000..31757a20259 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_perfschema/t/crash_tokudb.test @@ -0,0 +1,36 @@ +# TokuDB PFS crash test: +# Make sure FTI instrumentation is on, execute base DDL, DML queries +# and make sure there is no crash. + +--source include/not_embedded.inc +--source include/have_perfschema.inc +--source include/have_tokudb.inc + +SELECT COUNT(*) > 0 FROM performance_schema.setup_consumers + WHERE ENABLED = "NO"; +SELECT COUNT(*) > 0 FROM performance_schema.setup_instruments + WHERE NAME LIKE "%/fti/%" AND (ENABLED = 'NO' OR TIMED = "NO"); + +CREATE TABLE t(a INT AUTO_INCREMENT PRIMARY KEY, b INT) ENGINE=TokuDB; +INSERT INTO t (b) VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), + (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), + (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), + (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), + (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), + (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), + (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), + (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), + (1), (2), (3), (4), (5), (6), (7), (8), (9), (10), + (1), (2), (3), (4), (5), (6), (7), (8), (9), (10); +INSERT INTO t (b) SELECT b FROM t; + +UPDATE t SET b = 11 WHERE b = 10; +DELETE FROM t WHERE b = 1; + +ALTER TABLE t ADD COLUMN c CHAR(10) default NULL; +TRUNCATE TABLE t; +RENAME TABLE t TO t1; +RENAME TABLE t1 TO t; + +SELECT COUNT(*) > 0 FROM t; +DROP TABLE t; diff --git a/storage/tokudb/mysql-test/tokudb_perfschema/t/start_server_tokudb.test b/storage/tokudb/mysql-test/tokudb_perfschema/t/start_server_tokudb.test new file mode 100644 index 00000000000..4034fba0549 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_perfschema/t/start_server_tokudb.test @@ -0,0 +1,10 @@ +# Tests for PERFORMANCE_SCHEMA + +--source include/not_embedded.inc +--source include/have_perfschema.inc +--source include/have_tokudb.inc + +--source ../../perfschema/include/start_server_common.inc + +SELECT COUNT(NAME) > 0 FROM performance_schema.setup_instruments WHERE NAME LIKE "%/fti/%"; +SELECT COUNT(NAME) > 0 FROM performance_schema.threads WHERE NAME LIKE "%kibbutz%"; diff --git a/storage/tokudb/mysql-test/tokudb_perfschema/t/suite.opt b/storage/tokudb/mysql-test/tokudb_perfschema/t/suite.opt new file mode 100644 index 00000000000..6d826fe91d1 --- /dev/null +++ b/storage/tokudb/mysql-test/tokudb_perfschema/t/suite.opt @@ -0,0 +1 @@ +--loose-enable-performance-schema $TOKUDB_OPT $TOKUDB_LOAD_ADD --loose-tokudb-check-jemalloc=0 --loose-tokudb-cache-size=512M --loose-tokudb-block-size=1M diff --git a/storage/tokudb/tokudb_background.cc b/storage/tokudb/tokudb_background.cc index e019e41c788..13e0e9321cc 100644 --- a/storage/tokudb/tokudb_background.cc +++ b/storage/tokudb/tokudb_background.cc @@ -66,13 +66,13 @@ void job_manager_t::destroy() { _sem.set_interrupt(); while (_background_jobs.size()) { - _mutex.lock(); + mutex_t_lock(_mutex); job_t* job = _background_jobs.front(); if (!job->cancelled()) cancel(job); _background_jobs.pop_front(); delete job; - _mutex.unlock(); + mutex_t_unlock(_mutex); } void* result; @@ -83,7 +83,7 @@ bool job_manager_t::run_job(job_t* newjob, bool background) { bool ret = false; const char* jobkey = newjob->key(); - _mutex.lock(); + mutex_t_lock(_mutex); assert_always(!_shutdown); for (jobs_t::iterator it = _background_jobs.begin(); @@ -138,15 +138,16 @@ bool job_manager_t::run_job(job_t* newjob, bool background) { } cleanup: - _mutex.unlock(); + mutex_t_unlock(_mutex); return ret; } bool job_manager_t::cancel_job(const char* key) { bool ret = false; - _mutex.lock(); + mutex_t_lock(_mutex); for (jobs_t::iterator it = _background_jobs.begin(); - it != _background_jobs.end(); it++) { + it != _background_jobs.end(); + it++) { job_t* job = *it; if (!job->cancelled() && strcmp(job->key(), key) == 0) { @@ -155,12 +156,11 @@ bool job_manager_t::cancel_job(const char* key) { } } - _mutex.unlock(); + mutex_t_unlock(_mutex); return ret; } void job_manager_t::iterate_jobs(pfn_iterate_t callback, void* extra) const { - - _mutex.lock(); + mutex_t_lock(_mutex); for (jobs_t::const_iterator it = _background_jobs.begin(); it != _background_jobs.end(); @@ -171,7 +171,7 @@ void job_manager_t::iterate_jobs(pfn_iterate_t callback, void* extra) const { } } - _mutex.unlock(); + mutex_t_unlock(_mutex); } void* job_manager_t::thread_func(void* v) { return ((tokudb::background::job_manager_t*)v)->real_thread_func(); @@ -189,14 +189,14 @@ void* job_manager_t::real_thread_func() { tokudb::time::sleep_microsec(250000); continue; } -#endif // TOKUDB_DEBUG +#endif // TOKUDB_DEBUG - _mutex.lock(); + mutex_t_lock(_mutex); assert_debug(_background_jobs.size() > 0); job_t* job = _background_jobs.front(); run(job); _background_jobs.pop_front(); - _mutex.unlock(); + mutex_t_unlock(_mutex); delete job; } } @@ -205,11 +205,11 @@ void* job_manager_t::real_thread_func() { void job_manager_t::run(job_t* job) { assert_debug(_mutex.is_owned_by_me()); if (!job->cancelled()) { - _mutex.unlock(); + mutex_t_unlock(_mutex); // do job job->run(); // done job - _mutex.lock(); + mutex_t_lock(_mutex); } if (!job->cancelled()) { job->destroy(); diff --git a/storage/tokudb/tokudb_background.h b/storage/tokudb/tokudb_background.h index 29991ab325d..bf5eb97a619 100644 --- a/storage/tokudb/tokudb_background.h +++ b/storage/tokudb/tokudb_background.h @@ -174,11 +174,11 @@ bool destroy(); inline void job_manager_t::lock() { assert_debug(!_mutex.is_owned_by_me()); - _mutex.lock(); + mutex_t_lock(_mutex); } inline void job_manager_t::unlock() { assert_debug(_mutex.is_owned_by_me()); - _mutex.unlock(); + mutex_t_unlock(_mutex); } inline void job_manager_t::job_t::run() { diff --git a/storage/tokudb/tokudb_information_schema.cc b/storage/tokudb/tokudb_information_schema.cc index 5cd0609ac74..bb263d5f960 100644 --- a/storage/tokudb/tokudb_information_schema.cc +++ b/storage/tokudb/tokudb_information_schema.cc @@ -99,7 +99,7 @@ int trx_fill_table(THD* thd, TABLE_LIST* tables, COND* cond) { TOKUDB_DBUG_ENTER(""); int error; - tokudb_hton_initialized_lock.lock_read(); + rwlock_t_lock_read(tokudb_hton_initialized_lock); if (!tokudb_hton_initialized) { error = ER_PLUGIN_IS_NOT_LOADED; @@ -234,7 +234,7 @@ int lock_waits_fill_table(THD* thd, TABLE_LIST* tables, COND* cond) { TOKUDB_DBUG_ENTER(""); int error; - tokudb_hton_initialized_lock.lock_read(); + rwlock_t_lock_read(tokudb_hton_initialized_lock); if (!tokudb_hton_initialized) { error = ER_PLUGIN_IS_NOT_LOADED; @@ -377,7 +377,7 @@ int locks_fill_table(THD* thd, TABLE_LIST* tables, COND* cond) { TOKUDB_DBUG_ENTER(""); int error; - tokudb_hton_initialized_lock.lock_read(); + rwlock_t_lock_read(tokudb_hton_initialized_lock); if (!tokudb_hton_initialized) { error = ER_PLUGIN_IS_NOT_LOADED; @@ -521,7 +521,7 @@ int file_map_fill_table(THD* thd, TABLE_LIST* tables, COND* cond) { int error; TABLE* table = tables->table; - tokudb_hton_initialized_lock.lock_read(); + rwlock_t_lock_read(tokudb_hton_initialized_lock); if (!tokudb_hton_initialized) { error = ER_PLUGIN_IS_NOT_LOADED; @@ -728,7 +728,7 @@ int fractal_tree_info_fill_table(THD* thd, TABLE_LIST* tables, COND* cond) { // 3938: Get a read lock on the status flag, since we must // read it before safely proceeding - tokudb_hton_initialized_lock.lock_read(); + rwlock_t_lock_read(tokudb_hton_initialized_lock); if (!tokudb_hton_initialized) { error = ER_PLUGIN_IS_NOT_LOADED; @@ -1025,7 +1025,7 @@ int fractal_tree_block_map_fill_table( // 3938: Get a read lock on the status flag, since we must // read it before safely proceeding - tokudb_hton_initialized_lock.lock_read(); + rwlock_t_lock_read(tokudb_hton_initialized_lock); if (!tokudb_hton_initialized) { error = ER_PLUGIN_IS_NOT_LOADED; @@ -1162,7 +1162,7 @@ int background_job_status_fill_table(THD *thd, TABLE_LIST *tables, COND *cond) { int error; TABLE* table = tables->table; - tokudb_hton_initialized_lock.lock_read(); + rwlock_t_lock_read(tokudb_hton_initialized_lock); if (!tokudb_hton_initialized) { error = ER_PLUGIN_IS_NOT_LOADED; diff --git a/storage/tokudb/tokudb_thread.cc b/storage/tokudb/tokudb_thread.cc index f27e803a065..6fc1191975d 100644 --- a/storage/tokudb/tokudb_thread.cc +++ b/storage/tokudb/tokudb_thread.cc @@ -29,6 +29,7 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. namespace tokudb { namespace thread { +const pfs_key_t pfs_not_instrumented = 0xFFFFFFFF; pthread_t mutex_t::_null_owner = 0; } // namespace thread diff --git a/storage/tokudb/tokudb_thread.h b/storage/tokudb/tokudb_thread.h index dcb1fd6ec63..dec58f3fd35 100644 --- a/storage/tokudb/tokudb_thread.h +++ b/storage/tokudb/tokudb_thread.h @@ -34,95 +34,68 @@ Copyright (c) 2006, 2015, Percona and/or its affiliates. All rights reserved. namespace tokudb { namespace thread { -#if (defined(__MACH__) || defined(__APPLE__)) && _POSIX_TIMERS <= 0 - -#define _x_min(a, b) ((a) < (b) ? (a) : (b)) - -#define timed_lock_define(timed_func_name, lock_type_name, lock_func_name) \ -inline int timed_func_name(lock_type_name *mutex, \ - const struct timespec *abs_timeout) { \ - int pthread_rc; \ - struct timespec remaining, slept, ts; \ - static const int sleep_step = 1000000; \ - \ - remaining = *abs_timeout; \ - while ((pthread_rc = lock_func_name(mutex)) == EBUSY) { \ - ts.tv_sec = 0; \ - ts.tv_nsec = (remaining.tv_sec > 0 ? \ - sleep_step : \ - _x_min(remaining.tv_nsec,sleep_step)); \ - nanosleep(&ts, &slept); \ - ts.tv_nsec -= slept.tv_nsec; \ - if (ts.tv_nsec <= remaining.tv_nsec) { \ - remaining.tv_nsec -= ts.tv_nsec; \ - } else { \ - remaining.tv_sec--; \ - remaining.tv_nsec = \ - (sleep_step - (ts.tv_nsec - remaining.tv_nsec)); \ - } \ - if (remaining.tv_sec < 0 || \ - (!remaining.tv_sec && remaining.tv_nsec <= 0)) { \ - return ETIMEDOUT; \ - } \ - } \ - \ - return pthread_rc; \ -} - -timed_lock_define(pthread_mutex_timedlock, - pthread_mutex_t, - pthread_mutex_trylock); - -timed_lock_define(pthread_rwlock_timedrdlock, - pthread_rwlock_t, - pthread_rwlock_tryrdlock); - -timed_lock_define(pthread_rwlock_timedwrlock, - pthread_rwlock_t, - pthread_rwlock_trywrlock); - -#endif //(defined(__MACH__) || defined(__APPLE__)) && _POSIX_TIMERS <= 0 +extern const pfs_key_t pfs_not_instrumented; uint my_tid(void); // Your basic mutex class mutex_t { public: - mutex_t(void); + explicit mutex_t(pfs_key_t key); + mutex_t(void) : mutex_t(pfs_not_instrumented) {} ~mutex_t(void); - void lock(void); - int lock(ulonglong microseconds); - void unlock(void); + void reinit(pfs_key_t key); + void lock( +#ifdef HAVE_PSI_MUTEX_INTERFACE + const char* src_file, + uint src_line +#endif // HAVE_PSI_MUTEX_INTERFACE + ); + void unlock( +#ifdef HAVE_PSI_MUTEX_INTERFACE + const char* src_file, + uint src_line +#endif // HAVE_PSI_MUTEX_INTERFACE + ); #ifdef TOKUDB_DEBUG bool is_owned_by_me(void) const; #endif private: static pthread_t _null_owner; - pthread_mutex_t _mutex; + mysql_mutex_t _mutex; #ifdef TOKUDB_DEBUG - uint _owners; - pthread_t _owner; + uint _owners; + pthread_t _owner; #endif }; // Simple read write lock class rwlock_t { public: - rwlock_t(void); + explicit rwlock_t(pfs_key_t key); + rwlock_t(void) : rwlock_t(pfs_not_instrumented) {} ~rwlock_t(void); - void lock_read(void); - int lock_read(ulonglong microseconds); - void lock_write(void); - int lock_write(ulonglong microseconds); + void lock_read( +#ifdef HAVE_PSI_RWLOCK_INTERFACE + const char* src_file, + uint src_line +#endif // HAVE_PSI_RWLOCK_INTERFACE + ); + void lock_write( +#ifdef HAVE_PSI_RWLOCK_INTERFACE + const char* src_file, + uint src_line +#endif // HAVE_PSI_RWLOCK_INTERFACE + ); void unlock(void); private: rwlock_t(const rwlock_t&); rwlock_t& operator=(const rwlock_t&); - pthread_rwlock_t _rwlock; + mysql_rwlock_t _rwlock; }; // Simple event signal/wait class @@ -224,57 +197,76 @@ private: pthread_t _thread; }; +inline uint my_tid(void) { return (uint)toku_os_gettid(); } -inline uint my_tid(void) { - return (uint)toku_os_gettid(); -} - - -inline mutex_t::mutex_t(void) { - #ifdef TOKUDB_DEBUG - _owners = 0; - _owner = _null_owner; - #endif - int r = pthread_mutex_init(&_mutex, MY_MUTEX_INIT_FAST); +inline mutex_t::mutex_t(pfs_key_t key) { +#ifdef TOKUDB_DEBUG + _owners = 0; + _owner = _null_owner; +#endif + int r MY_ATTRIBUTE((unused)) = mysql_mutex_init(key, &_mutex, MY_MUTEX_INIT_FAST); assert_debug(r == 0); } inline mutex_t::~mutex_t(void) { - #ifdef TOKUDB_DEBUG - assert_debug(_owners == 0); - #endif - int r = pthread_mutex_destroy(&_mutex); +#ifdef TOKUDB_DEBUG + assert_debug(_owners == 0); +#endif + int r MY_ATTRIBUTE((unused)) = mysql_mutex_destroy(&_mutex); assert_debug(r == 0); } -inline void mutex_t::lock(void) { - assert_debug(is_owned_by_me() == false); - int r = pthread_mutex_lock(&_mutex); +inline void mutex_t::reinit(pfs_key_t key) { +#ifdef TOKUDB_DEBUG + assert_debug(_owners == 0); +#endif + int r MY_ATTRIBUTE((unused)); + r = mysql_mutex_destroy(&_mutex); + assert_debug(r == 0); + r = mysql_mutex_init(key, &_mutex, MY_MUTEX_INIT_FAST); assert_debug(r == 0); - #ifdef TOKUDB_DEBUG - _owners++; - _owner = pthread_self(); - #endif } -inline int mutex_t::lock(ulonglong microseconds) { +inline void mutex_t::lock( +#ifdef HAVE_PSI_MUTEX_INTERFACE + const char* src_file, + uint src_line +#endif // HAVE_PSI_MUTEX_INTERFACE + ) { assert_debug(is_owned_by_me() == false); - timespec waittime = time::offset_timespec(microseconds); - int r = pthread_mutex_timedlock(&_mutex, &waittime); - #ifdef TOKUDB_DEBUG - if (r == 0) { - _owners++; - _owner = pthread_self(); - } - #endif - assert_debug(r == 0 || r == ETIMEDOUT); - return r; + int r MY_ATTRIBUTE((unused)) = inline_mysql_mutex_lock(&_mutex +#ifdef HAVE_PSI_MUTEX_INTERFACE + , + src_file, + src_line +#endif // HAVE_PSI_MUTEX_INTERFACE + ); + assert_debug(r == 0); +#ifdef TOKUDB_DEBUG + _owners++; + _owner = pthread_self(); +#endif } -inline void mutex_t::unlock(void) { - #ifdef TOKUDB_DEBUG - assert_debug(_owners > 0); - assert_debug(is_owned_by_me()); - _owners--; - _owner = _null_owner; - #endif - int r = pthread_mutex_unlock(&_mutex); +inline void mutex_t::unlock( +#ifdef HAVE_PSI_MUTEX_INTERFACE + const char* src_file, + uint src_line +#endif // HAVE_PSI_MUTEX_INTERFACE + ) { +#ifndef SAFE_MUTEX + (void)(src_file); + (void)(src_line); +#endif // SAFE_MUTEX +#ifdef TOKUDB_DEBUG + assert_debug(_owners > 0); + assert_debug(is_owned_by_me()); + _owners--; + _owner = _null_owner; +#endif + int r MY_ATTRIBUTE((unused)) = inline_mysql_mutex_unlock(&_mutex +#ifdef SAFE_MUTEX + , + src_file, + src_line +#endif // SAFE_MUTEX + ); assert_debug(r == 0); } #ifdef TOKUDB_DEBUG @@ -283,44 +275,28 @@ inline bool mutex_t::is_owned_by_me(void) const { } #endif - -inline rwlock_t::rwlock_t(void) { - int r = pthread_rwlock_init(&_rwlock, NULL); +inline rwlock_t::rwlock_t(pfs_key_t key) { + int r MY_ATTRIBUTE((unused)) = mysql_rwlock_init(key, &_rwlock); assert_debug(r == 0); } inline rwlock_t::~rwlock_t(void) { - int r = pthread_rwlock_destroy(&_rwlock); - assert_debug(r == 0); -} -inline void rwlock_t::lock_read(void) { - int r; - while ((r = pthread_rwlock_rdlock(&_rwlock)) != 0) { - if (r == EBUSY || r == EAGAIN) { - time::sleep_microsec(1000); - continue; - } - break; - } - assert_debug(r == 0); -} -inline int rwlock_t::lock_read(ulonglong microseconds) { - int r; - timespec waittime = time::offset_timespec(microseconds); - while ((r = pthread_rwlock_timedrdlock(&_rwlock, &waittime)) != 0) { - if (r == EBUSY || r == EAGAIN) { - time::sleep_microsec(1000); - continue; - } else if (r == ETIMEDOUT) { - return ETIMEDOUT; - } - break; - } + int r MY_ATTRIBUTE((unused)) = mysql_rwlock_destroy(&_rwlock); assert_debug(r == 0); - return r; } -inline void rwlock_t::lock_write(void) { +inline void rwlock_t::lock_read( +#ifdef HAVE_PSI_RWLOCK_INTERFACE + const char* src_file, + uint src_line +#endif // HAVE_PSI_RWLOCK_INTERFACE + ) { int r; - while ((r = pthread_rwlock_wrlock(&_rwlock)) != 0) { + while ((r = inline_mysql_rwlock_rdlock(&_rwlock +#ifdef HAVE_PSI_RWLOCK_INTERFACE + , + src_file, + src_line +#endif // HAVE_PSI_RWLOCK_INTERFACE + )) != 0) { if (r == EBUSY || r == EAGAIN) { time::sleep_microsec(1000); continue; @@ -329,27 +305,33 @@ inline void rwlock_t::lock_write(void) { } assert_debug(r == 0); } -inline int rwlock_t::lock_write(ulonglong microseconds) { +inline void rwlock_t::lock_write( +#ifdef HAVE_PSI_RWLOCK_INTERFACE + const char* src_file, + uint src_line +#endif // HAVE_PSI_RWLOCK_INTERFACE + ) { int r; - timespec waittime = time::offset_timespec(microseconds); - while ((r = pthread_rwlock_timedwrlock(&_rwlock, &waittime)) != 0) { + while ((r = inline_mysql_rwlock_wrlock(&_rwlock +#ifdef HAVE_PSI_RWLOCK_INTERFACE + , + src_file, + src_line +#endif // HAVE_PSI_RWLOCK_INTERFACE + )) != 0) { if (r == EBUSY || r == EAGAIN) { time::sleep_microsec(1000); continue; - } else if (r == ETIMEDOUT) { - return ETIMEDOUT; } break; } assert_debug(r == 0); - return r; } inline void rwlock_t::unlock(void) { - int r = pthread_rwlock_unlock(&_rwlock); + int r MY_ATTRIBUTE((unused)) = mysql_rwlock_unlock(&_rwlock); assert_debug(r == 0); } -inline rwlock_t::rwlock_t(const rwlock_t&) { -} +inline rwlock_t::rwlock_t(const rwlock_t&) {} inline rwlock_t& rwlock_t::operator=(const rwlock_t&) { return *this; } @@ -358,7 +340,7 @@ inline rwlock_t& rwlock_t::operator=(const rwlock_t&) { inline event_t::event_t(bool create_signalled, bool manual_reset) : _manual_reset(manual_reset) { - int r = pthread_mutex_init(&_mutex, NULL); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_init(&_mutex, NULL); assert_debug(r == 0); r = pthread_cond_init(&_cond, NULL); assert_debug(r == 0); @@ -370,13 +352,13 @@ inline event_t::event_t(bool create_signalled, bool manual_reset) : _pulsed = false; } inline event_t::~event_t(void) { - int r = pthread_mutex_destroy(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_destroy(&_mutex); assert_debug(r == 0); r = pthread_cond_destroy(&_cond); assert_debug(r == 0); } inline void event_t::wait(void) { - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); while (_signalled == false && _pulsed == false) { r = pthread_cond_wait(&_cond, &_mutex); @@ -413,7 +395,7 @@ inline int event_t::wait(ulonglong microseconds) { return 0; } inline void event_t::signal(void) { - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); _signalled = true; if (_manual_reset) { @@ -427,7 +409,7 @@ inline void event_t::signal(void) { assert_debug(r == 0); } inline void event_t::pulse(void) { - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); _pulsed = true; r = pthread_cond_signal(&_cond); @@ -437,7 +419,7 @@ inline void event_t::pulse(void) { } inline bool event_t::signalled(void) { bool ret = false; - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); ret = _signalled; r = pthread_mutex_unlock(&_mutex); @@ -445,7 +427,7 @@ inline bool event_t::signalled(void) { return ret; } inline void event_t::reset(void) { - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); _signalled = false; _pulsed = false; @@ -467,21 +449,21 @@ inline semaphore_t::semaphore_t( _initial_count(initial_count), _max_count(max_count) { - int r = pthread_mutex_init(&_mutex, NULL); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_init(&_mutex, NULL); assert_debug(r == 0); r = pthread_cond_init(&_cond, NULL); assert_debug(r == 0); _signalled = _initial_count; } inline semaphore_t::~semaphore_t(void) { - int r = pthread_mutex_destroy(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_destroy(&_mutex); assert_debug(r == 0); r = pthread_cond_destroy(&_cond); assert_debug(r == 0); } inline semaphore_t::E_WAIT semaphore_t::wait(void) { E_WAIT ret; - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); while (_signalled == 0 && _interrupted == false) { r = pthread_cond_wait(&_cond, &_mutex); @@ -524,7 +506,7 @@ inline semaphore_t::E_WAIT semaphore_t::wait(ulonglong microseconds) { } inline bool semaphore_t::signal(void) { bool ret = false; - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); if (_signalled < _max_count) { _signalled++; @@ -538,7 +520,7 @@ inline bool semaphore_t::signal(void) { } inline int semaphore_t::signalled(void) { int ret = 0; - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); ret = _signalled; r = pthread_mutex_unlock(&_mutex); @@ -546,7 +528,7 @@ inline int semaphore_t::signalled(void) { return ret; } inline void semaphore_t::reset(void) { - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); _signalled = 0; r = pthread_mutex_unlock(&_mutex); @@ -554,7 +536,7 @@ inline void semaphore_t::reset(void) { return; } inline void semaphore_t::set_interrupt(void) { - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); _interrupted = true; r = pthread_cond_broadcast(&_cond); @@ -563,7 +545,7 @@ inline void semaphore_t::set_interrupt(void) { assert_debug(r == 0); } inline void semaphore_t::clear_interrupt(void) { - int r = pthread_mutex_lock(&_mutex); + int r MY_ATTRIBUTE((unused)) = pthread_mutex_lock(&_mutex); assert_debug(r == 0); _interrupted = false; r = pthread_mutex_unlock(&_mutex); diff --git a/storage/xtradb/api/api0api.cc b/storage/xtradb/api/api0api.cc index 0aae482b9f5..05360ac6218 100644 --- a/storage/xtradb/api/api0api.cc +++ b/storage/xtradb/api/api0api.cc @@ -398,7 +398,7 @@ ib_read_tuple( data = btr_rec_copy_externally_stored_field( copy, offsets, zip_size, i, &len, - tuple->heap, NULL); + tuple->heap); ut_a(len != UNIV_SQL_NULL); } diff --git a/storage/xtradb/btr/btr0cur.cc b/storage/xtradb/btr/btr0cur.cc index f22871deb32..e29d9091f8e 100644 --- a/storage/xtradb/btr/btr0cur.cc +++ b/storage/xtradb/btr/btr0cur.cc @@ -3991,7 +3991,6 @@ static const ib_int64_t rows_in_range_arbitrary_ret_val = 10; @param[in] mode1 search mode for range start @param[in] tuple2 range end, may also be empty tuple @param[in] mode2 search mode for range end -@param[in] trx trx @param[in] nth_attempt if the tree gets modified too much while we are trying to analyze it, then we will retry (this function will call itself, incrementing this parameter) @@ -4008,7 +4007,6 @@ btr_estimate_n_rows_in_range_low( ulint mode1, const dtuple_t* tuple2, ulint mode2, - trx_t* trx, unsigned nth_attempt) { btr_path_t path1[BTR_PATH_ARRAY_N_SLOTS]; @@ -4027,7 +4025,7 @@ btr_estimate_n_rows_in_range_low( table_n_rows = dict_table_get_n_rows(index->table); - mtr_start_trx(&mtr, trx); + mtr_start(&mtr); cursor.path_arr = path1; @@ -4049,7 +4047,7 @@ btr_estimate_n_rows_in_range_low( return (0); } - mtr_start_trx(&mtr, trx); + mtr_start(&mtr); #ifdef UNIV_DEBUG if (!strcmp(index->name, "iC")) { @@ -4144,7 +4142,7 @@ btr_estimate_n_rows_in_range_low( const ib_int64_t ret = btr_estimate_n_rows_in_range_low( index, tuple1, mode1, - tuple2, mode2, trx, + tuple2, mode2, nth_attempt + 1); return(ret); @@ -4205,7 +4203,6 @@ btr_estimate_n_rows_in_range_low( @param[in] mode1 search mode for range start @param[in] tuple2 range end, may also be empty tuple @param[in] mode2 search mode for range end -@param[in] trx trx @return estimated number of rows */ ib_int64_t btr_estimate_n_rows_in_range( @@ -4213,11 +4210,10 @@ btr_estimate_n_rows_in_range( const dtuple_t* tuple1, ulint mode1, const dtuple_t* tuple2, - ulint mode2, - trx_t* trx) + ulint mode2) { const ib_int64_t ret = btr_estimate_n_rows_in_range_low( - index, tuple1, mode1, tuple2, mode2, trx, + index, tuple1, mode1, tuple2, mode2, 1 /* first attempt */); return(ret); @@ -5757,8 +5753,7 @@ btr_copy_blob_prefix( ulint len, /*!< in: length of buf, in bytes */ ulint space_id,/*!< in: space id of the BLOB pages */ ulint page_no,/*!< in: page number of the first BLOB page */ - ulint offset, /*!< in: offset on the first BLOB page */ - trx_t* trx) /*!< in: transaction handle */ + ulint offset) /*!< in: offset on the first BLOB page */ { ulint copied_len = 0; @@ -5770,7 +5765,7 @@ btr_copy_blob_prefix( ulint part_len; ulint copy_len; - mtr_start_trx(&mtr, trx); + mtr_start(&mtr); block = buf_page_get(space_id, 0, page_no, RW_S_LATCH, &mtr); buf_block_dbg_add_level(block, SYNC_EXTERN_STORAGE); @@ -5973,8 +5968,7 @@ btr_copy_externally_stored_field_prefix_low( zero for uncompressed BLOBs */ ulint space_id,/*!< in: space id of the first BLOB page */ ulint page_no,/*!< in: page number of the first BLOB page */ - ulint offset, /*!< in: offset on the first BLOB page */ - trx_t* trx) /*!< in: transaction handle */ + ulint offset) /*!< in: offset on the first BLOB page */ { if (UNIV_UNLIKELY(len == 0)) { return(0); @@ -5985,7 +5979,7 @@ btr_copy_externally_stored_field_prefix_low( space_id, page_no, offset)); } else { return(btr_copy_blob_prefix(buf, len, space_id, - page_no, offset, trx)); + page_no, offset)); } } @@ -6006,8 +6000,7 @@ btr_copy_externally_stored_field_prefix( field containing also the reference to the external part; must be protected by a lock or a page latch */ - ulint local_len,/*!< in: length of data, in bytes */ - trx_t* trx) /*!< in: transaction handle */ + ulint local_len)/*!< in: length of data, in bytes */ { ulint space_id; ulint page_no; @@ -6046,7 +6039,7 @@ btr_copy_externally_stored_field_prefix( len - local_len, zip_size, space_id, page_no, - offset, trx)); + offset)); } /*******************************************************************//** @@ -6065,8 +6058,7 @@ btr_copy_externally_stored_field( ulint zip_size,/*!< in: nonzero=compressed BLOB page size, zero for uncompressed BLOBs */ ulint local_len,/*!< in: length of data */ - mem_heap_t* heap, /*!< in: mem heap */ - trx_t* trx) /*!< in: transaction handle */ + mem_heap_t* heap) /*!< in: mem heap */ { ulint space_id; ulint page_no; @@ -6097,8 +6089,7 @@ btr_copy_externally_stored_field( extern_len, zip_size, space_id, - page_no, offset, - trx); + page_no, offset); return(buf); } @@ -6117,8 +6108,7 @@ btr_rec_copy_externally_stored_field( zero for uncompressed BLOBs */ ulint no, /*!< in: field number */ ulint* len, /*!< out: length of the field */ - mem_heap_t* heap, /*!< in: mem heap */ - trx_t* trx) /*!< in: transaction handle */ + mem_heap_t* heap) /*!< in: mem heap */ { ulint local_len; const byte* data; @@ -6149,7 +6139,6 @@ btr_rec_copy_externally_stored_field( } return(btr_copy_externally_stored_field(len, data, - zip_size, local_len, heap, - trx)); + zip_size, local_len, heap)); } #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/xtradb/btr/btr0pcur.cc b/storage/xtradb/btr/btr0pcur.cc index 0b970e1cf49..06166e1aa16 100644 --- a/storage/xtradb/btr/btr0pcur.cc +++ b/storage/xtradb/btr/btr0pcur.cc @@ -33,6 +33,7 @@ Created 2/23/1996 Heikki Tuuri #include "rem0cmp.h" #include "trx0trx.h" #include "srv0srv.h" + /**************************************************************//** Allocates memory for a persistent cursor object and initializes the cursor. @return own: persistent cursor */ @@ -511,7 +512,7 @@ btr_pcur_move_backward_from_page( mtr_commit(mtr); - mtr_start_trx(mtr, mtr->trx); + mtr_start(mtr); btr_pcur_restore_position(latch_mode2, cursor, mtr); diff --git a/storage/xtradb/buf/buf0buddy.cc b/storage/xtradb/buf/buf0buddy.cc index 2ee39c6c992..1c50e71e687 100644 --- a/storage/xtradb/buf/buf0buddy.cc +++ b/storage/xtradb/buf/buf0buddy.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 2006, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, MariaDB Corporation. 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 @@ -667,7 +668,7 @@ buf_buddy_free_low( ut_ad(buf_pool->buddy_stat[i].used > 0); buf_pool->buddy_stat[i].used--; recombine: - UNIV_MEM_ASSERT_AND_ALLOC(buf, BUF_BUDDY_LOW << i); + UNIV_MEM_ALLOC(buf, BUF_BUDDY_LOW << i); if (i == BUF_BUDDY_SIZES) { mutex_exit(&buf_pool->zip_free_mutex); diff --git a/storage/xtradb/buf/buf0lru.cc b/storage/xtradb/buf/buf0lru.cc index a84f2a832f3..7bf423ed740 100644 --- a/storage/xtradb/buf/buf0lru.cc +++ b/storage/xtradb/buf/buf0lru.cc @@ -2070,7 +2070,7 @@ buf_LRU_block_free_non_file_page( ut_d(block->page.in_free_list = TRUE); mutex_exit(&buf_pool->free_list_mutex); - UNIV_MEM_ASSERT_AND_FREE(block->frame, UNIV_PAGE_SIZE); + UNIV_MEM_FREE(block->frame, UNIV_PAGE_SIZE); } /******************************************************************//** diff --git a/storage/xtradb/buf/buf0rea.cc b/storage/xtradb/buf/buf0rea.cc index 76b71550710..43e678ed7d4 100644 --- a/storage/xtradb/buf/buf0rea.cc +++ b/storage/xtradb/buf/buf0rea.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2013, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2017, MariaDB Corporation. +Copyright (c) 2013, 2018, MariaDB Corporation. 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 @@ -124,7 +124,12 @@ not exist or is being dropped use to stop dangling page reads from a tablespace which we have DISCARDed + IMPORTed back @param[in] offset page number -@param[in] trx transaction +@param[in,out] trx transaction +@param[in] should_buffer whether to buffer an aio request. + AIO read ahead uses this. If you plan to + use this parameter, make sure you remember + to call os_aio_dispatch_read_array_submit() + when you're ready to commit all your requests @return 1 if read request is issued. 0 if it is not */ static ulint @@ -137,7 +142,8 @@ buf_read_page_low( ibool unzip, ib_int64_t tablespace_version, ulint offset, - trx_t* trx = NULL) + trx_t* trx = NULL, + bool should_buffer = false) { buf_page_t* bpage; ulint wake_later; @@ -240,17 +246,18 @@ not_to_recover: } if (zip_size) { - *err = _fil_io(OS_FILE_READ | wake_later - | ignore_nonexistent_pages, - sync, space, zip_size, offset, 0, zip_size, - frame, bpage, 0, trx); + *err = fil_io(OS_FILE_READ | wake_later + | ignore_nonexistent_pages, + sync, space, zip_size, offset, 0, zip_size, + frame, bpage, 0, trx, should_buffer); } else { ut_a(buf_page_get_state(bpage) == BUF_BLOCK_FILE_PAGE); - *err = _fil_io(OS_FILE_READ | wake_later + *err = fil_io(OS_FILE_READ | wake_later | ignore_nonexistent_pages, sync, space, 0, offset, 0, UNIV_PAGE_SIZE, - frame, bpage, &bpage->write_size, trx); + frame, bpage, &bpage->write_size, + trx, should_buffer); } if (sync) { @@ -848,7 +855,7 @@ buf_read_ahead_linear( &err, false, ibuf_mode, space, zip_size, FALSE, tablespace_version, - i, trx); + i, trx, true); switch(err) { case DB_SUCCESS: @@ -876,6 +883,7 @@ buf_read_ahead_linear( } } } + os_aio_dispatch_read_array_submit(); /* In simulated aio we wake the aio handler threads only after queuing all aio requests, in native aio the following call does @@ -952,7 +960,7 @@ buf_read_ibuf_merge_pages( buf_read_page_low(&err, sync && (i + 1 == n_stored), BUF_READ_ANY_PAGE, space_ids[i], zip_size, TRUE, space_versions[i], - page_nos[i], NULL); + page_nos[i]); switch(err) { case DB_SUCCESS: @@ -1100,13 +1108,12 @@ not_to_recover: if ((i + 1 == n_stored) && sync) { buf_read_page_low(&err, true, BUF_READ_ANY_PAGE, space, zip_size, TRUE, tablespace_version, - page_nos[i], NULL); + page_nos[i]); } else { buf_read_page_low(&err, false, BUF_READ_ANY_PAGE | OS_AIO_SIMULATED_WAKE_LATER, space, zip_size, TRUE, - tablespace_version, page_nos[i], - NULL); + tablespace_version, page_nos[i]); } if (err == DB_DECRYPTION_FAILED) { diff --git a/storage/xtradb/data/data0type.cc b/storage/xtradb/data/data0type.cc index 0b9e08544a5..34ca399f9b2 100644 --- a/storage/xtradb/data/data0type.cc +++ b/storage/xtradb/data/data0type.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, MariaDB Corporation. 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 @@ -49,8 +50,10 @@ ulint dtype_get_at_most_n_mbchars( /*========================*/ ulint prtype, /*!< in: precise type */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of - a multi-byte character */ + ulint mbminlen, /*!< in: minimum length of + a multi-byte character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of + a multi-byte character, in bytes */ ulint prefix_len, /*!< in: length of the requested prefix, in characters, multiplied by dtype_get_mbmaxlen(dtype) */ @@ -58,9 +61,6 @@ dtype_get_at_most_n_mbchars( const char* str) /*!< in: the string whose prefix length is being determined */ { - ulint mbminlen = DATA_MBMINLEN(mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN(mbminmaxlen); - ut_a(data_len != UNIV_SQL_NULL); ut_ad(!mbmaxlen || !(prefix_len % mbmaxlen)); diff --git a/storage/xtradb/dict/dict0mem.cc b/storage/xtradb/dict/dict0mem.cc index 125d7d78a1f..cf27caf6c28 100644 --- a/storage/xtradb/dict/dict0mem.cc +++ b/storage/xtradb/dict/dict0mem.cc @@ -2,7 +2,7 @@ Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2017, MariaDB Corporation. +Copyright (c) 2013, 2018, MariaDB Corporation. 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 @@ -533,7 +533,8 @@ dict_mem_fill_column_struct( column->len = (unsigned int) col_len; #ifndef UNIV_HOTBACKUP dtype_get_mblen(mtype, prtype, &mbminlen, &mbmaxlen); - dict_col_set_mbminmaxlen(column, mbminlen, mbmaxlen); + column->mbminlen = mbminlen; + column->mbmaxlen = mbmaxlen; #endif /* !UNIV_HOTBACKUP */ } diff --git a/storage/xtradb/dict/dict0stats_bg.cc b/storage/xtradb/dict/dict0stats_bg.cc index e166e7df72a..884f62103f5 100644 --- a/storage/xtradb/dict/dict0stats_bg.cc +++ b/storage/xtradb/dict/dict0stats_bg.cc @@ -337,7 +337,7 @@ dict_stats_wait_bg_to_stop_using_table( unlocking/locking the data dict */ { while (!dict_stats_stop_bg(table)) { - DICT_STATS_BG_YIELD(trx); + DICT_BG_YIELD(trx); } } diff --git a/storage/xtradb/fil/fil0fil.cc b/storage/xtradb/fil/fil0fil.cc index 2ca605f15d0..54e6a891424 100644 --- a/storage/xtradb/fil/fil0fil.cc +++ b/storage/xtradb/fil/fil0fil.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2017, MariaDB Corporation. +Copyright (c) 2014, 2018, MariaDB Corporation. 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 @@ -2125,7 +2125,7 @@ fil_write_flushed_lsn( { byte* buf1; byte* buf; - dberr_t err; + dberr_t err = DB_TABLESPACE_NOT_FOUND; buf1 = static_cast<byte*>(ut_malloc(2 * UNIV_PAGE_SIZE)); buf = static_cast<byte*>(ut_align(buf1, UNIV_PAGE_SIZE)); @@ -4967,6 +4967,11 @@ will_not_choose: return; } + /* In mariabackup lets not crash. */ + if (IS_XTRABACKUP()) { + return; + } + abort(); } @@ -6056,7 +6061,7 @@ Reads or writes data. This operation is asynchronous (aio). i/o on a tablespace which does not exist */ UNIV_INTERN dberr_t -_fil_io( +fil_io( /*===*/ ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE, ORed to OS_FILE_LOG, if a log i/o @@ -6088,7 +6093,12 @@ _fil_io( operation for this page and if initialized we do not trim again if actual page size does not decrease. */ - trx_t* trx) + trx_t* trx, + bool should_buffer) /*!< in: whether to buffer an aio request. + AIO read ahead uses this. If you plan to + use this parameter, make sure you remember + to call os_aio_dispatch_read_array_submit() + when you're ready to commit all your requests.*/ { ulint mode; fil_space_t* space; @@ -6308,8 +6318,8 @@ _fil_io( /* Queue the aio request */ ret = os_aio(type, is_log, mode | wake_later, name, node->handle, buf, - offset, len, zip_size ? zip_size : UNIV_PAGE_SIZE, node, - message, space_id, trx, write_size); + offset, len, zip_size ? zip_size : UNIV_PAGE_SIZE, node, + message, space_id, trx, write_size, should_buffer); #else /* In mysqlbackup do normal i/o, not aio */ diff --git a/storage/xtradb/fts/fts0fts.cc b/storage/xtradb/fts/fts0fts.cc index 88b5ad97277..98aaf610f2a 100644 --- a/storage/xtradb/fts/fts0fts.cc +++ b/storage/xtradb/fts/fts0fts.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2011, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2016, 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -26,6 +26,7 @@ Full Text Search interface #include "row0mysql.h" #include "row0upd.h" #include "dict0types.h" +#include "dict0stats_bg.h" #include "row0sel.h" #include "fts0fts.h" @@ -868,18 +869,37 @@ fts_drop_index( err = fts_drop_index_tables(trx, index); - fts_free(table); - + for(;;) { + bool retry = false; + if (index->index_fts_syncing) { + retry = true; + } + if (!retry){ + fts_free(table); + break; + } + DICT_BG_YIELD(trx); + } return(err); } - current_doc_id = table->fts->cache->next_doc_id; - first_doc_id = table->fts->cache->first_doc_id; - fts_cache_clear(table->fts->cache); - fts_cache_destroy(table->fts->cache); - table->fts->cache = fts_cache_create(table); - table->fts->cache->next_doc_id = current_doc_id; - table->fts->cache->first_doc_id = first_doc_id; + for(;;) { + bool retry = false; + if (index->index_fts_syncing) { + retry = true; + } + if (!retry){ + current_doc_id = table->fts->cache->next_doc_id; + first_doc_id = table->fts->cache->first_doc_id; + fts_cache_clear(table->fts->cache); + fts_cache_destroy(table->fts->cache); + table->fts->cache = fts_cache_create(table); + table->fts->cache->next_doc_id = current_doc_id; + table->fts->cache->first_doc_id = first_doc_id; + break; + } + DICT_BG_YIELD(trx); + } } else { fts_cache_t* cache = table->fts->cache; fts_index_cache_t* index_cache; @@ -889,9 +909,17 @@ fts_drop_index( index_cache = fts_find_index_cache(cache, index); if (index_cache != NULL) { - if (index_cache->words) { - fts_words_free(index_cache->words); - rbt_free(index_cache->words); + for(;;) { + bool retry = false; + if (index->index_fts_syncing) { + retry = true; + } + if (!retry && index_cache->words) { + fts_words_free(index_cache->words); + rbt_free(index_cache->words); + break; + } + DICT_BG_YIELD(trx); } ib_vector_remove(cache->indexes, *(void**) index_cache); @@ -1973,7 +2001,7 @@ fts_create_one_index_table( ? DATA_VARCHAR : DATA_VARMYSQL, field->col->prtype, FTS_MAX_WORD_LEN_IN_CHAR - * DATA_MBMAXLEN(field->col->mbminmaxlen)); + * field->col->mbmaxlen); dict_mem_table_add_col(new_table, heap, "first_doc_id", DATA_INT, DATA_NOT_NULL | DATA_UNSIGNED, @@ -3333,8 +3361,7 @@ fts_fetch_doc_from_rec( dict_table_zip_size(table), clust_pos, &doc->text.f_len, static_cast<mem_heap_t*>( - doc->self_heap->arg), - NULL); + doc->self_heap->arg)); } else { doc->text.f_str = (byte*) rec_get_nth_field( clust_rec, offsets, clust_pos, @@ -4568,10 +4595,16 @@ begin_sync: index_cache = static_cast<fts_index_cache_t*>( ib_vector_get(cache->indexes, i)); - if (index_cache->index->to_be_dropped) { + if (index_cache->index->to_be_dropped + || index_cache->index->table->to_be_dropped) { continue; } + index_cache->index->index_fts_syncing = true; + DBUG_EXECUTE_IF("fts_instrument_sync_sleep_drop_waits", + os_thread_sleep(10000000); + ); + error = fts_sync_index(sync, index_cache); if (error != DB_SUCCESS && !sync->interrupted) { @@ -4604,11 +4637,33 @@ begin_sync: end_sync: if (error == DB_SUCCESS && !sync->interrupted) { error = fts_sync_commit(sync); + if (error == DB_SUCCESS) { + for (i = 0; i < ib_vector_size(cache->indexes); ++i) { + fts_index_cache_t* index_cache; + index_cache = static_cast<fts_index_cache_t*>( + ib_vector_get(cache->indexes, i)); + if (index_cache->index->index_fts_syncing) { + index_cache->index->index_fts_syncing + = false; + } + } + } } else { fts_sync_rollback(sync); } rw_lock_x_lock(&cache->lock); + /* Clear fts syncing flags of any indexes incase sync is + interrupeted */ + for (i = 0; i < ib_vector_size(cache->indexes); ++i) { + fts_index_cache_t* index_cache; + index_cache = static_cast<fts_index_cache_t*>( + ib_vector_get(cache->indexes, i)); + if (index_cache->index->index_fts_syncing == true) { + index_cache->index->index_fts_syncing = false; + } + } + sync->interrupted = false; sync->in_progress = false; os_event_set(sync->event); @@ -7535,8 +7590,7 @@ fts_init_recover_doc( &doc.text.f_len, static_cast<byte*>(dfield_get_data(dfield)), zip_size, len, - static_cast<mem_heap_t*>(doc.self_heap->arg), - NULL); + static_cast<mem_heap_t*>(doc.self_heap->arg)); } else { doc.text.f_str = static_cast<byte*>( dfield_get_data(dfield)); diff --git a/storage/xtradb/fts/fts0opt.cc b/storage/xtradb/fts/fts0opt.cc index cb30122adcb..d9f96948000 100644 --- a/storage/xtradb/fts/fts0opt.cc +++ b/storage/xtradb/fts/fts0opt.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2007, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2016, MariaDB Corporation. All Rights reserved. This program is free software; you can redistribute it and/or modify it under @@ -2971,13 +2971,6 @@ fts_optimize_sync_table( { dict_table_t* table = NULL; - /* Prevent DROP INDEX etc. from running when we are syncing - cache in background. */ - if (!rw_lock_s_lock_nowait(&dict_operation_lock, __FILE__, __LINE__)) { - /* Exit when fail to get dict operation lock. */ - return; - } - table = dict_table_open_on_id(table_id, FALSE, DICT_TABLE_OP_NORMAL); if (table) { @@ -2987,8 +2980,6 @@ fts_optimize_sync_table( dict_table_close(table, FALSE, FALSE); } - - rw_lock_s_unlock(&dict_operation_lock); } /**********************************************************************//** diff --git a/storage/xtradb/fts/fts0que.cc b/storage/xtradb/fts/fts0que.cc index 358d979fff6..0b0aecaeaa2 100644 --- a/storage/xtradb/fts/fts0que.cc +++ b/storage/xtradb/fts/fts0que.cc @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2007, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2007, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -1937,8 +1937,7 @@ fts_query_fetch_document( if (dfield_is_ext(dfield)) { data = btr_copy_externally_stored_field( &cur_len, data, phrase->zip_size, - dfield_get_len(dfield), phrase->heap, - NULL); + dfield_get_len(dfield), phrase->heap); } else { cur_len = dfield_get_len(dfield); } @@ -3656,6 +3655,7 @@ fts_query_free( if (query->intersection) { fts_query_free_doc_ids(query, query->intersection); + query->intersection = NULL; } if (query->doc_ids) { diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 8ec7b6535a2..396876999ce 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -1294,6 +1294,8 @@ static SHOW_VAR innodb_status_variables[]= { (char*) &export_vars.innodb_sec_rec_cluster_reads, SHOW_LONG}, {"secondary_index_triggered_cluster_reads_avoided", (char*) &export_vars.innodb_sec_rec_cluster_reads_avoided, SHOW_LONG}, + {"buffered_aio_submitted", + (char*) &export_vars.innodb_buffered_aio_submitted, SHOW_LONG}, /* Encryption */ {"encryption_rotation_pages_read_from_cache", @@ -12284,6 +12286,7 @@ index_bad: case ROW_TYPE_DEFAULT: /* If we fell through, set row format to Compact. */ row_format = ROW_TYPE_COMPACT; + /* fall through */ case ROW_TYPE_COMPACT: break; } @@ -13673,7 +13676,7 @@ ha_innobase::records_in_range( n_rows = btr_estimate_n_rows_in_range(index, range_start, mode1, range_end, - mode2, prebuilt->trx); + mode2); } else { n_rows = HA_POS_ERROR; @@ -21044,6 +21047,13 @@ static MYSQL_SYSVAR_BOOL(print_all_deadlocks, srv_print_all_deadlocks, "Print all deadlocks to MySQL error log (off by default)", NULL, NULL, FALSE); +static MYSQL_SYSVAR_BOOL( + print_lock_wait_timeout_info, + srv_print_lock_wait_timeout_info, + PLUGIN_VAR_OPCMDARG, + "Print lock wait timeout info to MySQL error log (off by default)", + NULL, NULL, FALSE); + static MYSQL_SYSVAR_ULONG(compression_failure_threshold_pct, zip_failure_threshold_pct, PLUGIN_VAR_OPCMDARG, "If the compression failure rate of a table is greater than this number" @@ -21502,6 +21512,7 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { MYSQL_SYSVAR(foreground_preflush), MYSQL_SYSVAR(empty_free_list_algorithm), MYSQL_SYSVAR(print_all_deadlocks), + MYSQL_SYSVAR(print_lock_wait_timeout_info), MYSQL_SYSVAR(cmp_per_index_enabled), MYSQL_SYSVAR(undo_logs), MYSQL_SYSVAR(rollback_segments), diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index 8fc0dc80363..70603499dad 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2017, MariaDB Corporation. All Rights Reserved. +Copyright (c) 2013, 2018, MariaDB Corporation. All Rights Reserved. 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 @@ -1200,8 +1200,7 @@ innobase_col_to_mysql( #ifdef UNIV_DEBUG case DATA_MYSQL: ut_ad(flen >= len); - ut_ad(DATA_MBMAXLEN(col->mbminmaxlen) - >= DATA_MBMINLEN(col->mbminmaxlen)); + ut_ad(col->mbmaxlen >= col->mbminlen); memcpy(dest, data, len); break; @@ -5917,7 +5916,47 @@ ha_innobase::commit_inplace_alter_table( break; } - DICT_STATS_BG_YIELD(trx); + DICT_BG_YIELD(trx); + } + + /* Make a concurrent Drop fts Index to wait until sync of that + fts index is happening in the background */ + for (;;) { + bool retry = false; + + for (inplace_alter_handler_ctx** pctx = ctx_array; + *pctx; pctx++) { + int count =0; + ha_innobase_inplace_ctx* ctx + = static_cast<ha_innobase_inplace_ctx*>(*pctx); + DBUG_ASSERT(new_clustered == ctx->need_rebuild()); + + if (dict_fts_index_syncing(ctx->old_table)) { + count++; + if (count == 100) { + fprintf(stderr, + "Drop index waiting for background sync" + "to finish\n"); + } + retry = true; + } + + if (new_clustered && dict_fts_index_syncing(ctx->new_table)) { + count++; + if (count == 100) { + fprintf(stderr, + "Drop index waiting for background sync" + "to finish\n"); + } + retry = true; + } + } + + if (!retry) { + break; + } + + DICT_BG_YIELD(trx); } /* Apply the changes to the data dictionary tables, for all @@ -6233,8 +6272,13 @@ foreign_fail: ut_d(dict_table_check_for_dup_indexes( ctx->new_table, CHECK_ABORTED_OK)); - ut_a(fts_check_cached_index(ctx->new_table)); +#ifdef UNIV_DEBUG + if (!(ctx->new_table->fts != NULL + && ctx->new_table->fts->cache->sync->in_progress)) { + ut_a(fts_check_cached_index(ctx->new_table)); + } +#endif if (new_clustered) { /* Since the table has been rebuilt, we remove all persistent statistics corresponding to the diff --git a/storage/xtradb/ibuf/ibuf0ibuf.cc b/storage/xtradb/ibuf/ibuf0ibuf.cc index 6925cd3abb5..b169916c34e 100644 --- a/storage/xtradb/ibuf/ibuf0ibuf.cc +++ b/storage/xtradb/ibuf/ibuf0ibuf.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1997, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2016, 2017, MariaDB Corporation. +Copyright (c) 2016, 2018, MariaDB Corporation. 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 @@ -4645,7 +4645,7 @@ ibuf_merge_or_delete_for_page( function. When the counter is > 0, that prevents tablespace from being dropped. */ - space = fil_space_acquire(space_id); + space = fil_space_acquire_silent(space_id); if (UNIV_UNLIKELY(!space)) { /* Do not try to read the bitmap page from space; diff --git a/storage/xtradb/include/btr0cur.h b/storage/xtradb/include/btr0cur.h index e478b33bf8e..1b0632e2120 100644 --- a/storage/xtradb/include/btr0cur.h +++ b/storage/xtradb/include/btr0cur.h @@ -568,8 +568,7 @@ btr_estimate_n_rows_in_range( const dtuple_t* tuple1, /*!< in: range start, may also be empty tuple */ ulint mode1, /*!< in: search mode for range start */ const dtuple_t* tuple2, /*!< in: range end, may also be empty tuple */ - ulint mode2, /*!< in: search mode for range end */ - trx_t* trx); /*!< in: trx */ + ulint mode2); /*!< in: search mode for range end */ /*******************************************************************//** Estimates the number of different key values in a given index, for each n-column prefix of the index where 1 <= n <= dict_index_get_n_unique(index). @@ -704,8 +703,7 @@ btr_copy_externally_stored_field_prefix( field containing also the reference to the external part; must be protected by a lock or a page latch */ - ulint local_len,/*!< in: length of data, in bytes */ - trx_t* trx); /*!< in: transaction handle */ + ulint local_len);/*!< in: length of data, in bytes */ /*******************************************************************//** Copies an externally stored field of a record to mem heap. The clustered index record must be protected by a lock or a page latch. @@ -722,8 +720,7 @@ btr_copy_externally_stored_field( ulint zip_size,/*!< in: nonzero=compressed BLOB page size, zero for uncompressed BLOBs */ ulint local_len,/*!< in: length of data */ - mem_heap_t* heap, /*!< in: mem heap */ - trx_t* trx); /*!< in: transaction handle */ + mem_heap_t* heap); /*!< in: mem heap */ /*******************************************************************//** Copies an externally stored field of a record to mem heap. @return the field copied to heap, or NULL if the field is incomplete */ @@ -738,8 +735,7 @@ btr_rec_copy_externally_stored_field( zero for uncompressed BLOBs */ ulint no, /*!< in: field number */ ulint* len, /*!< out: length of the field */ - mem_heap_t* heap, /*!< in: mem heap */ - trx_t* trx); /*!< in: transaction handle */ + mem_heap_t* heap); /*!< in: mem heap */ /*******************************************************************//** Flags the data tuple fields that are marked as extern storage in the update vector. We use this function to remember which fields we must diff --git a/storage/xtradb/include/data0type.h b/storage/xtradb/include/data0type.h index df6b6a41c11..f3ecab5a3ba 100644 --- a/storage/xtradb/include/data0type.h +++ b/storage/xtradb/include/data0type.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -182,18 +182,7 @@ store the charset-collation number; one byte is left unused, though */ #define DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE 6 /* Maximum multi-byte character length in bytes, plus 1 */ -#define DATA_MBMAX 5 - -/* Pack mbminlen, mbmaxlen to mbminmaxlen. */ -#define DATA_MBMINMAXLEN(mbminlen, mbmaxlen) \ - ((mbmaxlen) * DATA_MBMAX + (mbminlen)) -/* Get mbminlen from mbminmaxlen. Cast the result of UNIV_EXPECT to ulint -because in GCC it returns a long. */ -#define DATA_MBMINLEN(mbminmaxlen) ((ulint) \ - UNIV_EXPECT(((mbminmaxlen) % DATA_MBMAX), \ - 1)) -/* Get mbmaxlen from mbminmaxlen. */ -#define DATA_MBMAXLEN(mbminmaxlen) ((ulint) ((mbminmaxlen) / DATA_MBMAX)) +#define DATA_MBMAX 8 /* We now support 15 bits (up to 32767) collation number */ #define MAX_CHAR_COLL_NUM 32767 @@ -220,8 +209,10 @@ ulint dtype_get_at_most_n_mbchars( /*========================*/ ulint prtype, /*!< in: precise type */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of - a multi-byte character */ + ulint mbminlen, /*!< in: minimum length of + a multi-byte character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of + a multi-byte character, in bytes */ ulint prefix_len, /*!< in: length of the requested prefix, in characters, multiplied by dtype_get_mbmaxlen(dtype) */ @@ -366,19 +357,6 @@ dtype_get_mbmaxlen( /*===============*/ const dtype_t* type); /*!< in: type */ /*********************************************************************//** -Sets the minimum and maximum length of a character, in bytes. */ -UNIV_INLINE -void -dtype_set_mbminmaxlen( -/*==================*/ - dtype_t* type, /*!< in/out: type */ - ulint mbminlen, /*!< in: minimum length of a char, - in bytes, or 0 if this is not - a character type */ - ulint mbmaxlen); /*!< in: maximum length of a char, - in bytes, or 0 if this is not - a character type */ -/*********************************************************************//** Gets the padding character code for the type. @return padding character code, or ULINT_UNDEFINED if no padding specified */ UNIV_INLINE @@ -398,7 +376,9 @@ dtype_get_fixed_size_low( ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ ulint len, /*!< in: length */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of a + ulint mbminlen, /*!< in: minimum length of a + multibyte character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of a multibyte character, in bytes */ ulint comp); /*!< in: nonzero=ROW_FORMAT=COMPACT */ #ifndef UNIV_HOTBACKUP @@ -412,8 +392,8 @@ dtype_get_min_size_low( ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ ulint len, /*!< in: length */ - ulint mbminmaxlen); /*!< in: minimum and maximum length of a - multibyte character */ + ulint mbminlen, /*!< in: minimum length of a character */ + ulint mbmaxlen); /*!< in: maximum length of a character */ /***********************************************************************//** Returns the maximum size of a data type. Note: types in system tables may be incomplete and return incorrect information. @@ -530,11 +510,10 @@ struct dtype_t{ the string, MySQL uses 1 or 2 bytes to store the string length) */ #ifndef UNIV_HOTBACKUP - unsigned mbminmaxlen:5; /*!< minimum and maximum length of a - character, in bytes; - DATA_MBMINMAXLEN(mbminlen,mbmaxlen); - mbminlen=DATA_MBMINLEN(mbminmaxlen); - mbmaxlen=DATA_MBMINLEN(mbminmaxlen) */ + unsigned mbminlen:3; /*!< minimum length of a character, + in bytes */ + unsigned mbmaxlen:3; /*!< maximum length of a character, + in bytes */ #endif /* !UNIV_HOTBACKUP */ }; diff --git a/storage/xtradb/include/data0type.ic b/storage/xtradb/include/data0type.ic index ff72f6ed20f..96b001e197e 100644 --- a/storage/xtradb/include/data0type.ic +++ b/storage/xtradb/include/data0type.ic @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2012, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -105,27 +105,6 @@ dtype_get_mblen( } /*********************************************************************//** -Sets the minimum and maximum length of a character, in bytes. */ -UNIV_INLINE -void -dtype_set_mbminmaxlen( -/*==================*/ - dtype_t* type, /*!< in/out: type */ - ulint mbminlen, /*!< in: minimum length of a char, - in bytes, or 0 if this is not - a character type */ - ulint mbmaxlen) /*!< in: maximum length of a char, - in bytes, or 0 if this is not - a character type */ -{ - ut_ad(mbminlen < DATA_MBMAX); - ut_ad(mbmaxlen < DATA_MBMAX); - ut_ad(mbminlen <= mbmaxlen); - - type->mbminmaxlen = DATA_MBMINMAXLEN(mbminlen, mbmaxlen); -} - -/*********************************************************************//** Compute the mbminlen and mbmaxlen members of a data type structure. */ UNIV_INLINE void @@ -137,7 +116,8 @@ dtype_set_mblen( ulint mbmaxlen; dtype_get_mblen(type->mtype, type->prtype, &mbminlen, &mbmaxlen); - dtype_set_mbminmaxlen(type, mbminlen, mbmaxlen); + type->mbminlen = mbminlen; + type->mbmaxlen = mbmaxlen; ut_ad(dtype_validate(type)); } @@ -233,8 +213,7 @@ dtype_get_mbminlen( /*===============*/ const dtype_t* type) /*!< in: type */ { - ut_ad(type); - return(DATA_MBMINLEN(type->mbminmaxlen)); + return type->mbminlen; } /*********************************************************************//** Gets the maximum length of a character, in bytes. @@ -246,8 +225,7 @@ dtype_get_mbmaxlen( /*===============*/ const dtype_t* type) /*!< in: type */ { - ut_ad(type); - return(DATA_MBMAXLEN(type->mbminmaxlen)); + return type->mbmaxlen; } /*********************************************************************//** @@ -523,8 +501,10 @@ dtype_get_fixed_size_low( ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ ulint len, /*!< in: length */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of - a multibyte character, in bytes */ + ulint mbminlen, /*!< in: minimum length of a + multibyte character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of a + multibyte character, in bytes */ ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ { switch (mtype) { @@ -565,11 +545,10 @@ dtype_get_fixed_size_low( dtype_get_charset_coll(prtype), &i_mbminlen, &i_mbmaxlen); - ut_ad(DATA_MBMINMAXLEN(i_mbminlen, i_mbmaxlen) - == mbminmaxlen); + ut_ad(i_mbminlen == mbminlen); + ut_ad(i_mbmaxlen == mbmaxlen); #endif /* UNIV_DEBUG */ - if (DATA_MBMINLEN(mbminmaxlen) - == DATA_MBMAXLEN(mbminmaxlen)) { + if (mbminlen == mbmaxlen) { return(len); } } @@ -602,8 +581,8 @@ dtype_get_min_size_low( ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ ulint len, /*!< in: length */ - ulint mbminmaxlen) /*!< in: minimum and maximum length of a - multi-byte character */ + ulint mbminlen, /*!< in: minimum length of a character */ + ulint mbmaxlen) /*!< in: maximum length of a character */ { switch (mtype) { case DATA_SYS: @@ -633,9 +612,6 @@ dtype_get_min_size_low( if (prtype & DATA_BINARY_TYPE) { return(len); } else { - ulint mbminlen = DATA_MBMINLEN(mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN(mbminmaxlen); - if (mbminlen == mbmaxlen) { return(len); } @@ -706,9 +682,9 @@ dtype_get_sql_null_size( { #ifndef UNIV_HOTBACKUP return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len, - type->mbminmaxlen, comp)); + type->mbminlen, type->mbmaxlen, comp)); #else /* !UNIV_HOTBACKUP */ return(dtype_get_fixed_size_low(type->mtype, type->prtype, type->len, - 0, 0)); + 0, 0, 0)); #endif /* !UNIV_HOTBACKUP */ } diff --git a/storage/xtradb/include/dict0dict.h b/storage/xtradb/include/dict0dict.h index dda8f4d2714..241ed89e36b 100644 --- a/storage/xtradb/include/dict0dict.h +++ b/storage/xtradb/include/dict0dict.h @@ -2,7 +2,7 @@ Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2017, MariaDB Corporation. +Copyright (c) 2013, 2018, MariaDB Corporation. 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 @@ -197,18 +197,6 @@ dict_col_get_mbmaxlen( const dict_col_t* col) /*!< in: column */ MY_ATTRIBUTE((nonnull, warn_unused_result)); /*********************************************************************//** -Sets the minimum and maximum number of bytes per character. */ -UNIV_INLINE -void -dict_col_set_mbminmaxlen( -/*=====================*/ - dict_col_t* col, /*!< in/out: column */ - ulint mbminlen, /*!< in: minimum multi-byte - character size, in bytes */ - ulint mbmaxlen) /*!< in: minimum multi-byte - character size, in bytes */ - MY_ATTRIBUTE((nonnull)); -/*********************************************************************//** Gets the column data type. */ UNIV_INLINE void diff --git a/storage/xtradb/include/dict0dict.ic b/storage/xtradb/include/dict0dict.ic index f68d4e176da..8c50b961c58 100644 --- a/storage/xtradb/include/dict0dict.ic +++ b/storage/xtradb/include/dict0dict.ic @@ -1,7 +1,7 @@ /***************************************************************************** -Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2017, MariaDB Corporation. +Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2013, 2018, MariaDB Corporation. 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 @@ -41,7 +41,7 @@ dict_col_get_mbminlen( /*==================*/ const dict_col_t* col) /*!< in: column */ { - return(DATA_MBMINLEN(col->mbminmaxlen)); + return col->mbminlen; } /*********************************************************************//** Gets the maximum number of bytes per character. @@ -52,25 +52,7 @@ dict_col_get_mbmaxlen( /*==================*/ const dict_col_t* col) /*!< in: column */ { - return(DATA_MBMAXLEN(col->mbminmaxlen)); -} -/*********************************************************************//** -Sets the minimum and maximum number of bytes per character. */ -UNIV_INLINE -void -dict_col_set_mbminmaxlen( -/*=====================*/ - dict_col_t* col, /*!< in/out: column */ - ulint mbminlen, /*!< in: minimum multi-byte - character size, in bytes */ - ulint mbmaxlen) /*!< in: minimum multi-byte - character size, in bytes */ -{ - ut_ad(mbminlen < DATA_MBMAX); - ut_ad(mbmaxlen < DATA_MBMAX); - ut_ad(mbminlen <= mbmaxlen); - - col->mbminmaxlen = DATA_MBMINMAXLEN(mbminlen, mbmaxlen); + return col->mbmaxlen; } /*********************************************************************//** Gets the column data type. */ @@ -87,7 +69,8 @@ dict_col_copy_type( type->mtype = col->mtype; type->prtype = col->prtype; type->len = col->len; - type->mbminmaxlen = col->mbminmaxlen; + type->mbminlen = col->mbminlen; + type->mbmaxlen = col->mbmaxlen; } #endif /* !UNIV_HOTBACKUP */ @@ -109,7 +92,8 @@ dict_col_type_assert_equal( ut_ad(col->prtype == type->prtype); //ut_ad(col->len == type->len); # ifndef UNIV_HOTBACKUP - ut_ad(col->mbminmaxlen == type->mbminmaxlen); + ut_ad(col->mbminlen == type->mbminlen); + ut_ad(col->mbmaxlen == type->mbmaxlen); # endif /* !UNIV_HOTBACKUP */ return(TRUE); @@ -127,7 +111,7 @@ dict_col_get_min_size( const dict_col_t* col) /*!< in: column */ { return(dtype_get_min_size_low(col->mtype, col->prtype, col->len, - col->mbminmaxlen)); + col->mbminlen, col->mbmaxlen)); } /***********************************************************************//** Returns the maximum size of the column. @@ -152,7 +136,7 @@ dict_col_get_fixed_size( ulint comp) /*!< in: nonzero=ROW_FORMAT=COMPACT */ { return(dtype_get_fixed_size_low(col->mtype, col->prtype, col->len, - col->mbminmaxlen, comp)); + col->mbminlen, col->mbmaxlen, comp)); } /***********************************************************************//** Returns the ROW_FORMAT=REDUNDANT stored SQL NULL size of a column. @@ -1077,6 +1061,27 @@ dict_table_x_lock_indexes( } /*********************************************************************//** +Returns true if the particular FTS index in the table is still syncing +in the background, false otherwise. +@param [in] table Table containing FTS index +@return True if sync of fts index is still going in the background */ +UNIV_INLINE +bool +dict_fts_index_syncing( + dict_table_t* table) +{ + dict_index_t* index; + + for (index = dict_table_get_first_index(table); + index != NULL; + index = dict_table_get_next_index(index)) { + if (index->index_fts_syncing) { + return(true); + } + } + return(false); +} +/*********************************************************************//** Release the exclusive locks on all index tree. */ UNIV_INLINE void diff --git a/storage/xtradb/include/dict0mem.h b/storage/xtradb/include/dict0mem.h index 2a4422fc18b..bdec503c88c 100644 --- a/storage/xtradb/include/dict0mem.h +++ b/storage/xtradb/include/dict0mem.h @@ -1,8 +1,8 @@ /***************************************************************************** -Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2012, Facebook Inc. -Copyright (c) 2013, 2017, MariaDB Corporation. +Copyright (c) 2013, 2018, MariaDB Corporation. 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 @@ -538,11 +538,10 @@ struct dict_col_t{ the string, MySQL uses 1 or 2 bytes to store the string length) */ - unsigned mbminmaxlen:5; /*!< minimum and maximum length of a - character, in bytes; - DATA_MBMINMAXLEN(mbminlen,mbmaxlen); - mbminlen=DATA_MBMINLEN(mbminmaxlen); - mbmaxlen=DATA_MBMINLEN(mbminmaxlen) */ + unsigned mbminlen:3; /*!< minimum length of a + character, in bytes */ + unsigned mbmaxlen:3; /*!< maximum length of a + character, in bytes */ /*----------------------*/ /* End of definitions copied from dtype_t */ /* @} */ @@ -720,6 +719,8 @@ struct dict_index_t{ dict_sys->mutex. Other changes are protected by index->lock. */ dict_field_t* fields; /*!< array of field descriptions */ + bool index_fts_syncing;/*!< Whether the fts index is + still syncing in the background */ #ifndef UNIV_HOTBACKUP UT_LIST_NODE_T(dict_index_t) indexes;/*!< list of indexes of the table */ diff --git a/storage/xtradb/include/dict0stats_bg.h b/storage/xtradb/include/dict0stats_bg.h index 8f3385eb22b..66fcf7a0998 100644 --- a/storage/xtradb/include/dict0stats_bg.h +++ b/storage/xtradb/include/dict0stats_bg.h @@ -1,6 +1,6 @@ /***************************************************************************** -Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2012, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2017, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under @@ -83,7 +83,7 @@ dict_stats_defrag_pool_del( /** Yield the data dictionary latch when waiting for the background thread to stop accessing a table. @param trx transaction holding the data dictionary locks */ -#define DICT_STATS_BG_YIELD(trx) do { \ +#define DICT_BG_YIELD(trx) do { \ row_mysql_unlock_data_dictionary(trx); \ os_thread_sleep(250000); \ row_mysql_lock_data_dictionary(trx); \ diff --git a/storage/xtradb/include/fil0fil.h b/storage/xtradb/include/fil0fil.h index 5fe2d20b4f0..8c3bf7d2b06 100644 --- a/storage/xtradb/include/fil0fil.h +++ b/storage/xtradb/include/fil0fil.h @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1995, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2013, 2017, MariaDB Corporation. +Copyright (c) 2013, 2018, MariaDB Corporation. 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 @@ -1161,7 +1161,7 @@ Reads or writes data. This operation is asynchronous (aio). i/o on a tablespace which does not exist */ UNIV_INTERN dberr_t -_fil_io( +fil_io( /*===*/ ulint type, /*!< in: OS_FILE_READ or OS_FILE_WRITE, ORed to OS_FILE_LOG, if a log i/o @@ -1189,16 +1189,18 @@ _fil_io( void* message, /*!< in: message for aio handler if non-sync aio used, else ignored */ ulint* write_size, /*!< in/out: Actual write size initialized - after fist successfull trim - operation for this page and if - initialized we do not trim again if - actual page size does not decrease. */ - trx_t* trx) /*!< in: trx */ - - __attribute__((nonnull(8))); - -#define fil_io(type, sync, space_id, zip_size, block_offset, byte_offset, len, buf, message, write_size) \ - _fil_io(type, sync, space_id, zip_size, block_offset, byte_offset, len, buf, message, write_size, NULL) + after fist successfull trim + operation for this page and if + initialized we do not trim again if + actual page size does not decrease. */ + trx_t* trx = NULL, /*!< in: trx */ + bool should_buffer = false) + /*!< in: whether to buffer an aio request. + AIO read ahead uses this. If you plan to + use this parameter, make sure you remember + to call os_aio_dispatch_read_array_submit() + when you're ready to commit all your requests.*/ + MY_ATTRIBUTE((nonnull(8))); /** Determine the block size of the data file. @param[in] space tablespace diff --git a/storage/xtradb/include/log0online.h b/storage/xtradb/include/log0online.h index 5c3e7d07fd9..2d1febe9b9f 100644 --- a/storage/xtradb/include/log0online.h +++ b/storage/xtradb/include/log0online.h @@ -129,7 +129,11 @@ log_online_bitmap_iterator_next( /** Struct for single bitmap file information */ struct log_online_bitmap_file_struct { - char name[FN_REFLEN]; /*!< Name with full path */ + /** Name with full path + 61 is a nice magic constant for the extra space needed for the sprintf + template in the cc file + */ + char name[FN_REFLEN+61]; /*!< Name with full path */ pfs_os_file_t file; /*!< Handle to opened file */ ib_uint64_t size; /*!< Size of the file */ os_offset_t offset; /*!< Offset of the next read, diff --git a/storage/xtradb/include/mem0mem.ic b/storage/xtradb/include/mem0mem.ic index 63e68150b61..2b4638718fd 100644 --- a/storage/xtradb/include/mem0mem.ic +++ b/storage/xtradb/include/mem0mem.ic @@ -305,8 +305,8 @@ mem_heap_free_heap_top( mem_block_set_free(block, old_top - (byte*) block); ut_ad(mem_block_get_start(block) <= mem_block_get_free(block)); - UNIV_MEM_ASSERT_W(old_top, (byte*) block + block->len - old_top); #if defined UNIV_MEM_DEBUG + UNIV_MEM_ALLOC(old_top, (byte*)block + block->len - old_top); /* In the debug version erase block from top up */ mem_erase_buf(old_top, (byte*) block + block->len - old_top); @@ -315,7 +315,7 @@ mem_heap_free_heap_top( mem_current_allocated_memory -= (total_size - size); mutex_exit(&mem_hash_mutex); #endif /* UNIV_MEM_DEBUG */ - UNIV_MEM_ALLOC(old_top, (byte*) block + block->len - old_top); + UNIV_MEM_FREE(old_top, (byte*)block + block->len - old_top); /* If free == start, we may free the block if it is not the first one */ @@ -396,11 +396,11 @@ mem_heap_free_top( /* Subtract the free field of block */ mem_block_set_free(block, mem_block_get_free(block) - MEM_SPACE_NEEDED(n)); - UNIV_MEM_ASSERT_W((byte*) block + mem_block_get_free(block), n); #ifdef UNIV_MEM_DEBUG ut_ad(mem_block_get_start(block) <= mem_block_get_free(block)); + UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n); /* In the debug version check the consistency, and erase field */ mem_field_erase((byte*) block + mem_block_get_free(block), n); #endif @@ -412,11 +412,7 @@ mem_heap_free_top( == mem_block_get_start(block))) { mem_heap_block_free(heap, block); } else { - /* Avoid a bogus UNIV_MEM_ASSERT_W() warning in a - subsequent invocation of mem_heap_free_top(). - Originally, this was UNIV_MEM_FREE(), to catch writes - to freed memory. */ - UNIV_MEM_ALLOC((byte*) block + mem_block_get_free(block), n); + UNIV_MEM_FREE((byte*) block + mem_block_get_free(block), n); } } diff --git a/storage/xtradb/include/mtr0mtr.h b/storage/xtradb/include/mtr0mtr.h index ef6cd61719d..42a57f1022a 100644 --- a/storage/xtradb/include/mtr0mtr.h +++ b/storage/xtradb/include/mtr0mtr.h @@ -35,7 +35,6 @@ Created 11/26/1995 Heikki Tuuri #include "ut0byte.h" #include "mtr0types.h" #include "page0types.h" -#include "trx0types.h" /* Logging modes for a mini-transaction */ #define MTR_LOG_ALL 21 /* default mode: log all operations @@ -213,22 +212,10 @@ functions). The page number parameter was originally written as 0. @{ */ Starts a mini-transaction. */ UNIV_INLINE void -mtr_start_trx( -/*======*/ - mtr_t* mtr, /*!< out: mini-transaction */ - trx_t* trx) /*!< in: transaction */ - __attribute__((nonnull (1))); -/***************************************************************//** -Starts a mini-transaction. */ -UNIV_INLINE -void mtr_start( /*======*/ mtr_t* mtr) /*!< out: mini-transaction */ -{ - mtr_start_trx(mtr, NULL); -} - MY_ATTRIBUTE((nonnull)) + MY_ATTRIBUTE((nonnull)); /***************************************************************//** Commits a mini-transaction. */ UNIV_INTERN @@ -435,7 +422,6 @@ struct mtr_t{ #ifdef UNIV_DEBUG ulint magic_n; #endif /* UNIV_DEBUG */ - trx_t* trx; /*!< transaction */ }; #ifdef UNIV_DEBUG diff --git a/storage/xtradb/include/mtr0mtr.ic b/storage/xtradb/include/mtr0mtr.ic index a6d9df09925..04c39cf7f7e 100644 --- a/storage/xtradb/include/mtr0mtr.ic +++ b/storage/xtradb/include/mtr0mtr.ic @@ -43,10 +43,9 @@ mtr_block_dirtied( Starts a mini-transaction. */ UNIV_INLINE void -mtr_start_trx( +mtr_start( /*======*/ - mtr_t* mtr, /*!< out: mini-transaction */ - trx_t* trx) /*!< in: transaction */ + mtr_t* mtr) /*!< out: mini-transaction */ { UNIV_MEM_INVALID(mtr, sizeof *mtr); @@ -59,7 +58,6 @@ mtr_start_trx( mtr->made_dirty = FALSE; mtr->n_log_recs = 0; mtr->n_freed_pages = 0; - mtr->trx = trx; ut_d(mtr->state = MTR_ACTIVE); ut_d(mtr->magic_n = MTR_MAGIC_N); diff --git a/storage/xtradb/include/os0file.h b/storage/xtradb/include/os0file.h index f69230240c5..5e93b3454c7 100644 --- a/storage/xtradb/include/os0file.h +++ b/storage/xtradb/include/os0file.h @@ -382,11 +382,12 @@ The wrapper functions have the prefix of "innodb_". */ pfs_os_file_close_no_error_handling_func(file, __FILE__, __LINE__) # define os_aio(type, is_log, mode, name, file, buf, offset, \ - n, page_size, message1, message2, space_id, \ - trx, write_size) \ + n, page_size, message1, message2, space_id, \ + trx, write_size, should_buffer) \ pfs_os_aio_func(type, is_log, mode, name, file, buf, offset, \ - n, page_size, message1, message2, space_id, trx, write_size, \ - __FILE__, __LINE__) + n, page_size, message1, message2, space_id, \ + trx, write_size, should_buffer, \ + __FILE__, __LINE__) # define os_file_read(file, buf, offset, n) \ pfs_os_file_read_func(file, buf, offset, n, NULL, \ @@ -454,10 +455,12 @@ to original un-instrumented file I/O APIs */ # define os_file_close_no_error_handling(file) \ os_file_close_no_error_handling_func(file) -# define os_aio(type, is_log, mode, name, file, buf, offset, n, page_size, message1, \ - message2, space_id, trx, write_size) \ +# define os_aio(type, is_log, mode, name, file, buf, offset, \ + n, page_size, message1, \ + message2, space_id, trx, write_size, should_buffer) \ os_aio_func(type, is_log, mode, name, file, buf, offset, n, \ - page_size, message1, message2, space_id, trx, write_size) + page_size, message1, message2, space_id, \ + trx, write_size, should_buffer) # define os_file_read(file, buf, offset, n) \ os_file_read_func(file, buf, offset, n, NULL) @@ -939,6 +942,12 @@ pfs_os_aio_func( operation for this page and if initialized we do not trim again if actual page size does not decrease. */ + bool should_buffer, + /*!< in: Whether to buffer an aio request. + AIO read ahead uses this. If you plan to + use this parameter, make sure you remember + to call os_aio_dispatch_read_array_submit() + when you're ready to commit all your requests.*/ const char* src_file,/*!< in: file name where func invoked */ ulint src_line);/*!< in: line where the func invoked */ /*******************************************************************//** @@ -1359,11 +1368,17 @@ os_aio_func( OS_AIO_SYNC */ ulint space_id, trx_t* trx, - ulint* write_size);/*!< in/out: Actual write size initialized + ulint* write_size,/*!< in/out: Actual write size initialized after fist successfull trim operation for this page and if initialized we do not trim again if actual page size does not decrease. */ + bool should_buffer); + /*!< in: Whether to buffer an aio request. + AIO read ahead uses this. If you plan to + use this parameter, make sure you remember + to call os_aio_dispatch_read_array_submit() + when you're ready to commit all your requests.*/ /************************************************************************//** Wakes up all async i/o threads so that they know to exit themselves in shutdown. */ @@ -1547,6 +1562,10 @@ os_file_handle_error_no_exit( ibool on_error_silent);/*!< in: if TRUE then don't print any message to the log. */ +/** Submit buffered AIO requests on the given segment to the kernel. */ +UNIV_INTERN +void +os_aio_dispatch_read_array_submit(); /***********************************************************************//** Try to get number of bytes per sector from file system. diff --git a/storage/xtradb/include/os0file.ic b/storage/xtradb/include/os0file.ic index 72ac9d9dd6a..a2011da3545 100644 --- a/storage/xtradb/include/os0file.ic +++ b/storage/xtradb/include/os0file.ic @@ -258,6 +258,9 @@ pfs_os_aio_func( operation for this page and if initialized we do not trim again if actual page size does not decrease. */ + bool should_buffer, + /*!< in: whether to buffer an aio request. + Only used by aio read ahead*/ const char* src_file,/*!< in: file name where func invoked */ ulint src_line)/*!< in: line where the func invoked */ { @@ -274,7 +277,7 @@ pfs_os_aio_func( result = os_aio_func(type, is_log, mode, name, file, buf, offset, n, page_size, message1, message2, space_id, trx, - write_size); + write_size, should_buffer); register_pfs_file_io_end(locker, n); diff --git a/storage/xtradb/include/rem0rec.ic b/storage/xtradb/include/rem0rec.ic index 5811a77a48b..89f6902059d 100644 --- a/storage/xtradb/include/rem0rec.ic +++ b/storage/xtradb/include/rem0rec.ic @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, MariaDB Corporation. 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 @@ -922,7 +923,7 @@ rec_offs_set_n_alloc( { ut_ad(offsets); ut_ad(n_alloc > REC_OFFS_HEADER_SIZE); - UNIV_MEM_ASSERT_AND_ALLOC(offsets, n_alloc * sizeof *offsets); + UNIV_MEM_ALLOC(offsets, n_alloc * sizeof *offsets); offsets[0] = n_alloc; } diff --git a/storage/xtradb/include/row0mysql.h b/storage/xtradb/include/row0mysql.h index 4326f1208e5..4915e7c7a31 100644 --- a/storage/xtradb/include/row0mysql.h +++ b/storage/xtradb/include/row0mysql.h @@ -591,18 +591,6 @@ void row_mysql_close(void); /*=================*/ -/*********************************************************************//** -Reassigns the table identifier of a table. -@return error code or DB_SUCCESS */ -UNIV_INTERN -dberr_t -row_mysql_table_id_reassign( -/*========================*/ - dict_table_t* table, /*!< in/out: table */ - trx_t* trx, /*!< in/out: transaction */ - table_id_t* new_id) /*!< out: new table id */ - MY_ATTRIBUTE((nonnull, warn_unused_result)); - /* A struct describing a place for an individual column in the MySQL row format which is presented to the table handler in ha_innobase. This template struct is used to speed up row transformations between diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index 0e76340cdbd..7c778f7661f 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -195,6 +195,9 @@ struct srv_stats_t { wait timeout */ ulint_ctr_1_t n_lock_max_wait_time; + /** Number of buffered aio requests submitted */ + ulint_ctr_64_t n_aio_submitted; + /** Number of times page 0 is read from tablespace */ ulint_ctr_64_t page0_read; @@ -717,6 +720,9 @@ extern ulong srv_sync_array_size; /* print all user-level transactions deadlocks to mysqld stderr */ extern my_bool srv_print_all_deadlocks; +/* print lock wait timeout info to mysqld stderr */ +extern my_bool srv_print_lock_wait_timeout_info; + extern my_bool srv_cmp_per_index_enabled; /* is encryption enabled */ @@ -1291,7 +1297,9 @@ struct export_var_t{ ib_int64_t innodb_n_rowlog_blocks_decrypted; ulint innodb_sec_rec_cluster_reads; /*!< srv_sec_rec_cluster_reads */ - ulint innodb_sec_rec_cluster_reads_avoided;/*!< srv_sec_rec_cluster_reads_avoided */ + ulint innodb_sec_rec_cluster_reads_avoided; /*!< srv_sec_rec_cluster_reads_avoided */ + + ulint innodb_buffered_aio_submitted; ulint innodb_encryption_rotation_pages_read_from_cache; ulint innodb_encryption_rotation_pages_read_from_disk; diff --git a/storage/xtradb/include/trx0rec.h b/storage/xtradb/include/trx0rec.h index ec15250ec7b..fef12548003 100644 --- a/storage/xtradb/include/trx0rec.h +++ b/storage/xtradb/include/trx0rec.h @@ -229,7 +229,7 @@ trx_undo_report_row_operation( const ulint* offsets, /*!< in: rec_get_offsets(rec) */ roll_ptr_t* roll_ptr) /*!< out: DB_ROLL_PTR to the undo log record */ - MY_ATTRIBUTE((nonnull(1,2,8), warn_unused_result)); + MY_ATTRIBUTE((nonnull(2,8), warn_unused_result)); /******************************************************************//** Copies an undo record to heap. This function can be called if we know that the undo log record exists. diff --git a/storage/xtradb/include/trx0undo.h b/storage/xtradb/include/trx0undo.h index 190308112ba..0148cc61579 100644 --- a/storage/xtradb/include/trx0undo.h +++ b/storage/xtradb/include/trx0undo.h @@ -243,13 +243,22 @@ Truncates an undo log from the end. This function is used during a rollback to free space from an undo log. */ UNIV_INTERN void -trx_undo_truncate_end( +trx_undo_truncate_end_func( /*=======================*/ - trx_t* trx, /*!< in: transaction whose undo log it is */ +#ifdef UNIV_DEBUG + const trx_t* trx, /*!< in: transaction whose undo log it is */ +#endif /* UNIV_DEBUG */ trx_undo_t* undo, /*!< in/out: undo log */ undo_no_t limit) /*!< in: all undo records with undo number >= this value should be truncated */ MY_ATTRIBUTE((nonnull)); +#ifdef UNIV_DEBUG +# define trx_undo_truncate_end(trx,undo,limit) \ + trx_undo_truncate_end_func(trx,undo,limit) +#else /* UNIV_DEBUG */ +# define trx_undo_truncate_end(trx,undo,limit) \ + trx_undo_truncate_end_func(undo,limit) +#endif /* UNIV_DEBUG */ /***********************************************************************//** Truncates an undo log from the start. This function is used during a purge diff --git a/storage/xtradb/include/univ.i b/storage/xtradb/include/univ.i index 5886b078e4d..93ab71bf46c 100644 --- a/storage/xtradb/include/univ.i +++ b/storage/xtradb/include/univ.i @@ -48,7 +48,7 @@ Created 1/20/1994 Heikki Tuuri #define INNODB_VERSION_BUGFIX 36 #ifndef PERCONA_INNODB_VERSION -#define PERCONA_INNODB_VERSION 82.2 +#define PERCONA_INNODB_VERSION 83.0 #endif /* Enable UNIV_LOG_ARCHIVE in XtraDB */ @@ -691,14 +691,6 @@ typedef void* os_thread_ret_t; # define UNIV_MEM_ASSERT_W(addr, size) do {} while(0) # define UNIV_MEM_TRASH(addr, c, size) do {} while(0) #endif -#define UNIV_MEM_ASSERT_AND_FREE(addr, size) do { \ - UNIV_MEM_ASSERT_W(addr, size); \ - UNIV_MEM_FREE(addr, size); \ -} while (0) -#define UNIV_MEM_ASSERT_AND_ALLOC(addr, size) do { \ - UNIV_MEM_ASSERT_W(addr, size); \ - UNIV_MEM_ALLOC(addr, size); \ -} while (0) extern ulong srv_page_size_shift; extern ulong srv_page_size; diff --git a/storage/xtradb/lock/lock0lock.cc b/storage/xtradb/lock/lock0lock.cc index 20e3f5adeb7..a9077cb19a3 100644 --- a/storage/xtradb/lock/lock0lock.cc +++ b/storage/xtradb/lock/lock0lock.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2017, MariaDB Corporation +Copyright (c) 2014, 2018, MariaDB Corporation. 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 @@ -6970,7 +6970,7 @@ lock_rec_block_validate( /* Make sure that the tablespace is not deleted while we are trying to access the page. */ - if (fil_space_t* space = fil_space_acquire(space_id)) { + if (fil_space_t* space = fil_space_acquire_silent(space_id)) { mtr_start(&mtr); block = buf_page_get_gen( diff --git a/storage/xtradb/lock/lock0wait.cc b/storage/xtradb/lock/lock0wait.cc index a0f557e18e5..da4b0301df8 100644 --- a/storage/xtradb/lock/lock0wait.cc +++ b/storage/xtradb/lock/lock0wait.cc @@ -33,6 +33,20 @@ Created 25/5/2010 Sunny Bains #include "srv0start.h" #include "ha_prototypes.h" #include "lock0priv.h" +#include "lock0iter.h" + +#include <sstream> + +extern "C" +LEX_STRING* thd_query_string(MYSQL_THD thd); + +struct blocking_trx_info { + uint64_t trx_id; + uint32_t thread_id; + int64_t query_id; +}; + +static const size_t MAX_BLOCKING_TRX_IN_REPORT = 10; #include <mysql/service_wsrep.h> @@ -187,6 +201,46 @@ lock_wait_table_reserve_slot( return(NULL); } +/** Print lock wait timeout info to stderr. It's supposed this function +is executed in trx's THD thread as it calls some non-thread-safe +functions to get some info from THD. +@param[in] trx requested trx +@param[in] blocking blocking info array +@param[in] blocking_count blocking info array size */ +void +print_lock_wait_timeout( + const trx_t &trx, + blocking_trx_info *blocking, + size_t blocking_count) +{ + std::ostringstream outs; + + outs << "Lock wait timeout info:\n"; + outs << "Requested thread id: " << + thd_get_thread_id(trx.mysql_thd) << + "\n"; + outs << "Requested trx id: " << trx.id << "\n"; + outs << "Requested query: " << + thd_query_string(trx.mysql_thd)->str << "\n"; + + outs << "Total blocking transactions count: " << + blocking_count << + "\n"; + + for (size_t i = 0; i < blocking_count; ++i) { + outs << "Blocking transaction number: " << (i + 1) << "\n"; + outs << "Blocking thread id: " << + blocking[i].thread_id << + "\n"; + outs << "Blocking query id: " << + blocking[i].query_id << + "\n"; + outs << "Blocking trx id: " << blocking[i].trx_id << "\n"; + } + ut_print_timestamp(stderr); + fprintf(stderr, " %s", outs.str().c_str()); +} + #ifdef WITH_WSREP /*********************************************************************//** check if lock timeout was for priority thread, @@ -235,6 +289,8 @@ lock_wait_suspend_thread( ulint sec; ulint ms; ulong lock_wait_timeout; + blocking_trx_info blocking[MAX_BLOCKING_TRX_IN_REPORT]; + size_t blocking_count = 0; trx = thr_get_trx(thr); @@ -411,6 +467,8 @@ lock_wait_suspend_thread( #endif /* WITH_WSREP */ trx->error_state = DB_LOCK_WAIT_TIMEOUT; + if (srv_print_lock_wait_timeout_info) + print_lock_wait_timeout(*trx, blocking, blocking_count); #ifdef WITH_WSREP } diff --git a/storage/xtradb/log/log0online.cc b/storage/xtradb/log/log0online.cc index 27382977e5c..af32237243b 100644 --- a/storage/xtradb/log/log0online.cc +++ b/storage/xtradb/log/log0online.cc @@ -479,9 +479,9 @@ log_online_make_bitmap_name( /*=========================*/ lsn_t start_lsn) /*!< in: the start LSN name part */ { - ut_snprintf(log_bmp_sys->out.name, FN_REFLEN, bmp_file_name_template, - log_bmp_sys->bmp_file_home, bmp_file_name_stem, - log_bmp_sys->out_seq_num, start_lsn); + ut_snprintf(log_bmp_sys->out.name, sizeof(log_bmp_sys->out.name), + bmp_file_name_template, log_bmp_sys->bmp_file_home, + bmp_file_name_stem, log_bmp_sys->out_seq_num, start_lsn); } /*********************************************************************//** diff --git a/storage/xtradb/mem/mem0mem.cc b/storage/xtradb/mem/mem0mem.cc index e066aff5b30..b9f190509ee 100644 --- a/storage/xtradb/mem/mem0mem.cc +++ b/storage/xtradb/mem/mem0mem.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2011, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, MariaDB Corporation. 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 @@ -506,13 +507,13 @@ mem_heap_block_free( #ifndef UNIV_HOTBACKUP if (!srv_use_sys_malloc) { #ifdef UNIV_MEM_DEBUG + UNIV_MEM_ALLOC(block, len); /* In the debug version we set the memory to a random combination of hex 0xDE and 0xAD. */ - mem_erase_buf((byte*) block, len); -#else /* UNIV_MEM_DEBUG */ - UNIV_MEM_ASSERT_AND_FREE(block, len); + mem_erase_buf((byte*)block, len); #endif /* UNIV_MEM_DEBUG */ + UNIV_MEM_FREE(block, len); } if (type == MEM_HEAP_DYNAMIC || len < UNIV_PAGE_SIZE / 2) { @@ -526,13 +527,13 @@ mem_heap_block_free( } #else /* !UNIV_HOTBACKUP */ #ifdef UNIV_MEM_DEBUG + UNIV_MEM_ALLOC(block, len); /* In the debug version we set the memory to a random combination of hex 0xDE and 0xAD. */ - mem_erase_buf((byte*) block, len); -#else /* UNIV_MEM_DEBUG */ - UNIV_MEM_ASSERT_AND_FREE(block, len); + mem_erase_buf((byte*)block, len); #endif /* UNIV_MEM_DEBUG */ + UNIV_MEM_FREE(block, len); ut_free(block); #endif /* !UNIV_HOTBACKUP */ } diff --git a/storage/xtradb/os/os0file.cc b/storage/xtradb/os/os0file.cc index 8b0fa059100..634ebb2af49 100644 --- a/storage/xtradb/os/os0file.cc +++ b/storage/xtradb/os/os0file.cc @@ -296,6 +296,16 @@ struct os_aio_array_t{ There is one such event for each possible pending IO. The size of the array is equal to n_slots. */ + struct iocb** pending; + /* Array to buffer the not-submitted aio + requests. The array length is n_slots. + It is divided into n_segments segments. + pending requests on each segment are buffered + separately.*/ + ulint* count; + /* Array of length n_segments. Each element + counts the number of not-submitted aio + request on that segment.*/ #endif /* LINUX_NATIV_AIO */ }; @@ -4276,6 +4286,13 @@ os_aio_array_create( memset(io_event, 0x0, sizeof(*io_event) * n); array->aio_events = io_event; + array->pending = static_cast<struct iocb**>( + ut_malloc(n * sizeof(struct iocb*))); + memset(array->pending, 0x0, sizeof(struct iocb*) * n); + array->count = static_cast<ulint*>( + ut_malloc(n_segments * sizeof(ulint))); + memset(array->count, 0x0, sizeof(ulint) * n_segments); + skip_native_aio: #endif /* LINUX_NATIVE_AIO */ for (ulint i = 0; i < n; i++) { @@ -4310,6 +4327,16 @@ os_aio_array_free( if (srv_use_native_aio) { ut_free(array->aio_events); ut_free(array->aio_ctx); + +#ifdef UNIV_DEBUG + for (size_t idx = 0; idx < array->n_slots; ++idx) + ut_ad(array->pending[idx] == NULL); + for (size_t idx = 0; idx < array->n_segments; ++idx) + ut_ad(array->count[idx] == 0); +#endif + + ut_free(array->pending); + ut_free(array->count); } #endif /* LINUX_NATIVE_AIO */ @@ -4957,6 +4984,83 @@ readahead requests. */ } #endif /* _WIN32 */ +/** Submit buffered AIO requests on the given segment to the kernel +(low level function). +@param acquire_mutex specifies whether to lock array mutex +*/ +static +void +os_aio_dispatch_read_array_submit_low(bool acquire_mutex MY_ATTRIBUTE((unused))) +{ + if (!srv_use_native_aio) { + return; + } +#if defined(LINUX_NATIVE_AIO) + os_aio_array_t* array = os_aio_read_array; + ulint total_submitted = 0; + if (acquire_mutex) + os_mutex_enter(array->mutex); + /* Submit aio requests buffered on all segments. */ + for (ulint i = 0; i < array->n_segments; i++) { + const int count = array->count[i]; + int offset = 0; + while (offset != count) { + struct iocb** const iocb_array = array->pending + + i * array->n_slots / array->n_segments + + offset; + const int partial_count = count - offset; + /* io_submit() returns number of successfully queued + requests or (-errno). + It returns 0 only if the number of iocb blocks passed + is also 0. */ + const int submitted = io_submit(array->aio_ctx[i], + partial_count, iocb_array); + + /* This assertion prevents infinite loop in both + debug and release modes. */ + ut_a(submitted != 0); + + if (submitted < 0) { + /* Terminating with fatal error */ + const char* errmsg = + strerror(-submitted); + ib_logf(IB_LOG_LEVEL_FATAL, + "Trying to sumbit %d aio requests, " + "io_submit() set errno to %d: %s", + partial_count, -submitted, + errmsg ? errmsg : "<unknown>"); + } + ut_ad(submitted <= partial_count); + if (submitted < partial_count) + { + ib_logf(IB_LOG_LEVEL_WARN, + "Trying to sumbit %d aio requests, " + "io_submit() submitted only %d", + partial_count, submitted); + } + offset += submitted; + } + total_submitted += count; + } + /* Reset the aio request buffer. */ + memset(array->pending, 0x0, sizeof(struct iocb*) * array->n_slots); + memset(array->count, 0x0, sizeof(ulint) * array->n_segments); + + if (acquire_mutex) + os_mutex_exit(array->mutex); + + srv_stats.n_aio_submitted.add(total_submitted); +#endif +} + +/** Submit buffered AIO requests on the given segment to the kernel. */ +UNIV_INTERN +void +os_aio_dispatch_read_array_submit() +{ + os_aio_dispatch_read_array_submit_low(true); +} + #if defined(LINUX_NATIVE_AIO) /*******************************************************************//** Dispatch an AIO request to the kernel. @@ -4966,10 +5070,11 @@ ibool os_aio_linux_dispatch( /*==================*/ os_aio_array_t* array, /*!< in: io request array. */ - os_aio_slot_t* slot) /*!< in: an already reserved slot. */ + os_aio_slot_t* slot, /*!< in: an already reserved slot. */ + bool should_buffer) /*!< in: should buffer the request + rather than submit. */ { int ret; - ulint io_ctx_index; struct iocb* iocb; ut_ad(slot != NULL); @@ -4981,9 +5086,31 @@ os_aio_linux_dispatch( The iocb struct is directly in the slot. The io_context is one per segment. */ + ulint slots_per_segment = array->n_slots / array->n_segments; iocb = &slot->control; - io_ctx_index = (slot->pos * array->n_segments) / array->n_slots; + ulint io_ctx_index = slot->pos / slots_per_segment; + if (should_buffer) { + ut_ad(array == os_aio_read_array); + os_mutex_enter(array->mutex); + /* There are array->n_slots elements in array->pending, + which is divided into array->n_segments area of equal size. + The iocb of each segment are buffered in its corresponding area + in the pending array consecutively as they come. + array->count[i] records the number of buffered aio requests + in the ith segment.*/ + ulint& count = array->count[io_ctx_index]; + ut_ad(count != slots_per_segment); + ulint n = io_ctx_index * slots_per_segment + count; + array->pending[n] = iocb; + ++count; + if (count == slots_per_segment) { + os_aio_dispatch_read_array_submit_low(false); + } + os_mutex_exit(array->mutex); + return(TRUE); + } + /* Submit the given request. */ ret = io_submit(array->aio_ctx[io_ctx_index], 1, &iocb); #if defined(UNIV_AIO_DEBUG) @@ -5046,11 +5173,17 @@ os_aio_func( OS_AIO_SYNC */ ulint space_id, trx_t* trx, - ulint* write_size)/*!< in/out: Actual write size initialized + ulint* write_size,/*!< in/out: Actual write size initialized after fist successfull trim operation for this page and if initialized we do not trim again if actual page size does not decrease. */ + bool should_buffer) + /*!< in: Whether to buffer an aio request. + AIO read ahead uses this. If you plan to + use this parameter, make sure you remember + to call os_aio_dispatch_read_array_submit() + when you're ready to commit all your requests.*/ { os_aio_array_t* array; os_aio_slot_t* slot; @@ -5168,7 +5301,8 @@ try_again: goto err_exit; #elif defined(LINUX_NATIVE_AIO) - if (!os_aio_linux_dispatch(array, slot)) { + if (!os_aio_linux_dispatch(array, slot, + should_buffer)) { goto err_exit; } #endif /* WIN_ASYNC_IO */ @@ -5192,7 +5326,7 @@ try_again: if(!ret && GetLastError() != ERROR_IO_PENDING) goto err_exit; #elif defined(LINUX_NATIVE_AIO) - if (!os_aio_linux_dispatch(array, slot)) { + if (!os_aio_linux_dispatch(array, slot, false)) { goto err_exit; } #endif /* WIN_ASYNC_IO */ diff --git a/storage/xtradb/page/page0page.cc b/storage/xtradb/page/page0page.cc index 800f76e1532..fc93eebd445 100644 --- a/storage/xtradb/page/page0page.cc +++ b/storage/xtradb/page/page0page.cc @@ -2839,7 +2839,7 @@ page_warn_strict_checksum( ulint space_id, ulint page_no) { - srv_checksum_algorithm_t curr_algo_nonstrict; + srv_checksum_algorithm_t curr_algo_nonstrict = srv_checksum_algorithm_t(); switch (curr_algo) { case SRV_CHECKSUM_ALGORITHM_STRICT_CRC32: curr_algo_nonstrict = SRV_CHECKSUM_ALGORITHM_CRC32; diff --git a/storage/xtradb/rem/rem0rec.cc b/storage/xtradb/rem/rem0rec.cc index c62e8c90434..2314f110312 100644 --- a/storage/xtradb/rem/rem0rec.cc +++ b/storage/xtradb/rem/rem0rec.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1994, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -865,13 +865,10 @@ rec_get_converted_size_comp_prefix_low( if (fixed_len) { #ifdef UNIV_DEBUG - ulint mbminlen = DATA_MBMINLEN(col->mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN(col->mbminmaxlen); - ut_ad(len <= fixed_len); - ut_ad(!mbmaxlen || len >= mbminlen - * (fixed_len / mbmaxlen)); + ut_ad(!col->mbmaxlen || len >= col->mbminlen + * (fixed_len / col->mbmaxlen)); /* dict_index_add_col() should guarantee this */ ut_ad(!field->prefix_len @@ -1259,14 +1256,10 @@ rec_convert_dtuple_to_rec_comp( it is 128 or more, or when the field is stored externally. */ if (fixed_len) { #ifdef UNIV_DEBUG - ulint mbminlen = DATA_MBMINLEN( - ifield->col->mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN( - ifield->col->mbminmaxlen); - ut_ad(len <= fixed_len); - ut_ad(!mbmaxlen || len >= mbminlen - * (fixed_len / mbmaxlen)); + ut_ad(!ifield->col->mbmaxlen + || len >= ifield->col->mbminlen + * (fixed_len / ifield->col->mbmaxlen)); ut_ad(!dfield_is_ext(field)); #endif /* UNIV_DEBUG */ } else if (dfield_is_ext(field)) { diff --git a/storage/xtradb/row/row0ext.cc b/storage/xtradb/row/row0ext.cc index ad852577ad2..32b78391d6a 100644 --- a/storage/xtradb/row/row0ext.cc +++ b/storage/xtradb/row/row0ext.cc @@ -78,8 +78,7 @@ row_ext_cache_fill( crashed during the execution of btr_free_externally_stored_field(). */ ext->len[i] = btr_copy_externally_stored_field_prefix( - buf, ext->max_len, zip_size, field, f_len, - NULL); + buf, ext->max_len, zip_size, field, f_len); } } } diff --git a/storage/xtradb/row/row0ftsort.cc b/storage/xtradb/row/row0ftsort.cc index 0f9c15f6a69..bd57685b71c 100644 --- a/storage/xtradb/row/row0ftsort.cc +++ b/storage/xtradb/row/row0ftsort.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2010, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2017, MariaDB Corporation. +Copyright (c) 2015, 2018, MariaDB Corporation. 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 @@ -106,8 +106,9 @@ row_merge_create_fts_sort_index( field->col->prtype = idx_field->col->prtype | DATA_NOT_NULL; field->col->mtype = charset == &my_charset_latin1 ? DATA_VARCHAR : DATA_VARMYSQL; - field->col->mbminmaxlen = idx_field->col->mbminmaxlen; - field->col->len = HA_FT_MAXCHARLEN * DATA_MBMAXLEN(field->col->mbminmaxlen); + field->col->mbminlen = idx_field->col->mbminlen; + field->col->mbmaxlen = idx_field->col->mbmaxlen; + field->col->len = HA_FT_MAXCHARLEN * field->col->mbmaxlen; field->fixed_len = 0; @@ -150,7 +151,8 @@ row_merge_create_fts_sort_index( field->col->prtype = DATA_NOT_NULL | DATA_BINARY_TYPE; - field->col->mbminmaxlen = 0; + field->col->mbminlen = 0; + field->col->mbmaxlen = 0; /* The third field is on the word's position in the original doc */ field = dict_index_get_nth_field(new_index, 2); @@ -162,7 +164,8 @@ row_merge_create_fts_sort_index( field->col->len = 4 ; field->fixed_len = 4; field->col->prtype = DATA_NOT_NULL; - field->col->mbminmaxlen = 0; + field->col->mbminlen = 0; + field->col->mbmaxlen = 0; return(new_index); } @@ -540,7 +543,8 @@ row_merge_fts_doc_tokenize( field->type.mtype = DATA_INT; field->type.prtype = DATA_NOT_NULL | DATA_BINARY_TYPE; field->type.len = len; - field->type.mbminmaxlen = 0; + field->type.mbminlen = 0; + field->type.mbmaxlen = 0; cur_len += len; dfield_dup(field, buf->heap); @@ -559,7 +563,8 @@ row_merge_fts_doc_tokenize( field->type.mtype = DATA_INT; field->type.prtype = DATA_NOT_NULL; field->type.len = len; - field->type.mbminmaxlen = 0; + field->type.mbminlen = 0; + field->type.mbmaxlen = 0; cur_len += len; dfield_dup(field, buf->heap); @@ -709,8 +714,7 @@ loop: doc.text.f_str = btr_copy_externally_stored_field( &doc.text.f_len, data, - zip_size, data_len, blob_heap, - NULL); + zip_size, data_len, blob_heap); } else { doc.text.f_str = data; doc.text.f_len = data_len; diff --git a/storage/xtradb/row/row0import.cc b/storage/xtradb/row/row0import.cc index 7689c362c0d..117e1fd2771 100644 --- a/storage/xtradb/row/row0import.cc +++ b/storage/xtradb/row/row0import.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2017, MariaDB Corporation. +Copyright (c) 2015, 2018, MariaDB Corporation. 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 @@ -1259,7 +1259,8 @@ row_import::match_table_columns( err = DB_ERROR; } - if (cfg_col->mbminmaxlen != col->mbminmaxlen) { + if (cfg_col->mbminlen != col->mbminlen + || cfg_col->mbmaxlen != col->mbmaxlen) { ib_errf(thd, IB_LOG_LEVEL_ERROR, ER_TABLE_SCHEMA_MISMATCH, @@ -2877,7 +2878,9 @@ row_import_read_columns( col->len = mach_read_from_4(ptr); ptr += sizeof(ib_uint32_t); - col->mbminmaxlen = mach_read_from_4(ptr); + ulint mbminmaxlen = mach_read_from_4(ptr); + col->mbmaxlen = mbminmaxlen / 5; + col->mbminlen = mbminmaxlen % 5; ptr += sizeof(ib_uint32_t); col->ind = mach_read_from_4(ptr); diff --git a/storage/xtradb/row/row0ins.cc b/storage/xtradb/row/row0ins.cc index f653a4df77d..472be8ad848 100644 --- a/storage/xtradb/row/row0ins.cc +++ b/storage/xtradb/row/row0ins.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -571,7 +571,8 @@ row_ins_cascade_calc_update_vec( if (!dfield_is_null(&ufield->new_val) && dtype_get_at_most_n_mbchars( - col->prtype, col->mbminmaxlen, + col->prtype, + col->mbminlen, col->mbmaxlen, col->len, ufield_len, static_cast<char*>( @@ -1330,7 +1331,7 @@ row_ins_foreign_check_on_constraint( row_mysql_freeze_data_dictionary(thr_get_trx(thr)); - mtr_start_trx(mtr, trx); + mtr_start(mtr); /* Restore pcur position */ @@ -1358,7 +1359,7 @@ nonstandard_exit_func: btr_pcur_store_position(pcur, mtr); mtr_commit(mtr); - mtr_start_trx(mtr, trx); + mtr_start(mtr); btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr); @@ -1571,7 +1572,7 @@ run_again: } } - mtr_start_trx(&mtr, trx); + mtr_start(&mtr); /* Store old value on n_fields_cmp */ @@ -2390,7 +2391,7 @@ row_ins_clust_index_entry_low( search_mode = mode; } - mtr_start_trx(&mtr, thr_get_trx(thr)); + mtr_start(&mtr); if (mode == BTR_MODIFY_LEAF && dict_index_is_online_ddl(index)) { @@ -2628,10 +2629,9 @@ Starts a mini-transaction and checks if the index will be dropped. @return true if the index is to be dropped */ static MY_ATTRIBUTE((nonnull, warn_unused_result)) bool -row_ins_sec_mtr_start_trx_and_check_if_aborted( +row_ins_sec_mtr_start_and_check_if_aborted( /*=======================================*/ mtr_t* mtr, /*!< out: mini-transaction */ - trx_t* trx, /*!< in: transaction handle */ dict_index_t* index, /*!< in/out: secondary index */ bool check, /*!< in: whether to check */ ulint search_mode) @@ -2639,7 +2639,7 @@ row_ins_sec_mtr_start_trx_and_check_if_aborted( { ut_ad(!dict_index_is_clust(index)); - mtr_start_trx(mtr, trx); + mtr_start(mtr); if (!check) { return(false); @@ -2697,14 +2697,13 @@ row_ins_sec_index_entry_low( ulint n_unique; mtr_t mtr; ulint* offsets = NULL; - trx_t* trx = thr_get_trx(thr); ut_ad(!dict_index_is_clust(index)); ut_ad(mode == BTR_MODIFY_LEAF || mode == BTR_MODIFY_TREE); cursor.thr = thr; ut_ad(thr_get_trx(thr)->id); - mtr_start_trx(&mtr, trx); + mtr_start(&mtr); /* If running with fake_changes mode on then avoid using insert buffer and also switch from modify to search so that code takes only s-latch @@ -2766,7 +2765,7 @@ row_ins_sec_index_entry_low( if (err != DB_SUCCESS) { if (err == DB_DECRYPTION_FAILED) { - ib_push_warning(trx->mysql_thd, + ib_push_warning(thr_get_trx(thr)->mysql_thd, DB_DECRYPTION_FAILED, "Table %s is encrypted but encryption service or" " used key_id is not available. " @@ -2802,8 +2801,8 @@ row_ins_sec_index_entry_low( DEBUG_SYNC_C("row_ins_sec_index_unique"); - if (row_ins_sec_mtr_start_trx_and_check_if_aborted( - &mtr, trx, index, check, search_mode)) { + if (row_ins_sec_mtr_start_and_check_if_aborted( + &mtr, index, check, search_mode)) { goto func_exit; } @@ -2837,8 +2836,8 @@ row_ins_sec_index_entry_low( return(err); } - if (row_ins_sec_mtr_start_trx_and_check_if_aborted( - &mtr, trx, index, check, search_mode)) { + if (row_ins_sec_mtr_start_and_check_if_aborted( + &mtr, index, check, search_mode)) { goto func_exit; } @@ -3147,7 +3146,7 @@ row_ins_index_entry_set_vals( = dict_field_get_col(ind_field); len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminmaxlen, + col->prtype, col->mbminlen, col->mbmaxlen, ind_field->prefix_len, len, static_cast<const char*>( diff --git a/storage/xtradb/row/row0log.cc b/storage/xtradb/row/row0log.cc index 82fde841f39..040fb37ee30 100644 --- a/storage/xtradb/row/row0log.cc +++ b/storage/xtradb/row/row0log.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2011, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -1064,7 +1064,7 @@ row_log_table_get_pk_col( mem_heap_alloc(heap, field_len)); len = btr_copy_externally_stored_field_prefix( - blob_field, field_len, zip_size, field, len, NULL); + blob_field, field_len, zip_size, field, len); if (len >= max_len + 1) { return(DB_TOO_BIG_INDEX_COL); } @@ -1183,7 +1183,7 @@ row_log_table_get_pk( dict_field_t* ifield; dfield_t* dfield; ulint prtype; - ulint mbminmaxlen; + ulint mbminlen, mbmaxlen; ifield = dict_index_get_nth_field(new_index, new_i); dfield = dtuple_get_nth_field(tuple, new_i); @@ -1212,7 +1212,8 @@ err_exit: goto func_exit; } - mbminmaxlen = col->mbminmaxlen; + mbminlen = col->mbminlen; + mbmaxlen = col->mbmaxlen; prtype = col->prtype; } else { /* No matching column was found in the old @@ -1222,7 +1223,8 @@ err_exit: dfield_copy(dfield, dtuple_get_nth_field( log->add_cols, col_no)); - mbminmaxlen = dfield->type.mbminmaxlen; + mbminlen = dfield->type.mbminlen; + mbmaxlen = dfield->type.mbmaxlen; prtype = dfield->type.prtype; } @@ -1231,7 +1233,7 @@ err_exit: if (ifield->prefix_len) { ulint len = dtype_get_at_most_n_mbchars( - prtype, mbminmaxlen, + prtype, mbminlen, mbmaxlen, ifield->prefix_len, dfield_get_len(dfield), static_cast<const char*>( @@ -1455,7 +1457,7 @@ row_log_table_apply_convert_mrec( data = btr_rec_copy_externally_stored_field( mrec, offsets, dict_table_zip_size(index->table), - i, &len, heap, NULL); + i, &len, heap); ut_a(data); dfield_set_data(dfield, data, len); blob_done: diff --git a/storage/xtradb/row/row0merge.cc b/storage/xtradb/row/row0merge.cc index 22ad34e5e35..f26e765990f 100644 --- a/storage/xtradb/row/row0merge.cc +++ b/storage/xtradb/row/row0merge.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2005, 2017, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2017, MariaDB Corporation. +Copyright (c) 2014, 2018, MariaDB Corporation. 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 @@ -268,8 +268,8 @@ row_merge_buf_redundant_convert( mem_heap_t* heap, trx_t* trx) { - ut_ad(DATA_MBMINLEN(field->type.mbminmaxlen) == 1); - ut_ad(DATA_MBMAXLEN(field->type.mbminmaxlen) > 1); + ut_ad(field->type.mbminlen == 1); + ut_ad(field->type.mbmaxlen > 1); byte* buf = (byte*) mem_heap_alloc(heap, len); ulint field_len = row_field->len; @@ -285,7 +285,7 @@ row_merge_buf_redundant_convert( field_ref_zero, BTR_EXTERN_FIELD_REF_SIZE)); byte* data = btr_copy_externally_stored_field( - &ext_len, field_data, zip_size, field_len, heap, trx); + &ext_len, field_data, zip_size, field_len, heap); ut_ad(ext_len < len); @@ -396,7 +396,8 @@ row_merge_buf_add( field->type.mtype = ifield->col->mtype; field->type.prtype = ifield->col->prtype; - field->type.mbminmaxlen = DATA_MBMINMAXLEN(0, 0); + field->type.mbminlen = 0; + field->type.mbmaxlen = 0; field->type.len = ifield->col->len; } else { row_field = dtuple_get_nth_field(row, col_no); @@ -531,7 +532,7 @@ row_merge_buf_add( if (ifield->prefix_len) { len = dtype_get_at_most_n_mbchars( col->prtype, - col->mbminmaxlen, + col->mbminlen, col->mbmaxlen, ifield->prefix_len, len, static_cast<char*>(dfield_get_data(field))); @@ -546,8 +547,7 @@ row_merge_buf_add( fixed_len = ifield->fixed_len; if (fixed_len && !dict_table_is_comp(index->table) - && DATA_MBMINLEN(col->mbminmaxlen) - != DATA_MBMAXLEN(col->mbminmaxlen)) { + && col->mbminlen != col->mbmaxlen) { /* CHAR in ROW_FORMAT=REDUNDANT is always fixed-length, but in the temporary file it is variable-length for variable-length character @@ -557,14 +557,11 @@ row_merge_buf_add( if (fixed_len) { #ifdef UNIV_DEBUG - ulint mbminlen = DATA_MBMINLEN(col->mbminmaxlen); - ulint mbmaxlen = DATA_MBMAXLEN(col->mbminmaxlen); - /* len should be between size calcualted base on mbmaxlen and mbminlen */ ut_ad(len <= fixed_len); - ut_ad(!mbmaxlen || len >= mbminlen - * (fixed_len / mbmaxlen)); + ut_ad(!col->mbmaxlen || len >= col->mbminlen + * (fixed_len / col->mbmaxlen)); ut_ad(!dfield_is_ext(field)); #endif /* UNIV_DEBUG */ @@ -2626,7 +2623,7 @@ row_merge_copy_blobs( BLOB pointers are read (row_merge_read_clustered_index()) and dereferenced (below). */ data = btr_rec_copy_externally_stored_field( - mrec, offsets, zip_size, i, &len, heap, NULL); + mrec, offsets, zip_size, i, &len, heap); /* Because we have locked the table, any records written by incomplete transactions must have been rolled back already. There must not be any incomplete diff --git a/storage/xtradb/row/row0mysql.cc b/storage/xtradb/row/row0mysql.cc index 43f4d4bcdd3..549a19799b3 100644 --- a/storage/xtradb/row/row0mysql.cc +++ b/storage/xtradb/row/row0mysql.cc @@ -1,7 +1,7 @@ /***************************************************************************** -Copyright (c) 2000, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2015, 2017, MariaDB Corporation. +Copyright (c) 2000, 2017, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2015, 2018, MariaDB Corporation. 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 @@ -58,6 +58,7 @@ Created 9/17/2000 Heikki Tuuri #include "btr0sea.h" #include "btr0defragment.h" #include "fil0fil.h" +#include "srv0srv.h" #include "fil0crypt.h" #include "ibuf0ibuf.h" #include "fts0fts.h" @@ -1998,7 +1999,7 @@ row_unlock_for_mysql( trx_id_t rec_trx_id; mtr_t mtr; - mtr_start_trx(&mtr, trx); + mtr_start(&mtr); /* Restore the cursor position and find the record */ @@ -2888,7 +2889,7 @@ func_exit: /*********************************************************************//** Reassigns the table identifier of a table. @return error code or DB_SUCCESS */ -UNIV_INTERN +static dberr_t row_mysql_table_id_reassign( /*========================*/ @@ -3585,7 +3586,7 @@ row_truncate_table_for_mysql( index = dict_table_get_next_index(index); } while (index); - mtr_start_trx(&mtr, trx); + mtr_start(&mtr); fsp_header_init(space_id, FIL_IBD_FILE_INITIAL_SIZE, &mtr); mtr_commit(&mtr); @@ -3614,7 +3615,7 @@ row_truncate_table_for_mysql( sys_index = dict_table_get_first_index(dict_sys->sys_indexes); dict_index_copy_types(tuple, sys_index, 1); - mtr_start_trx(&mtr, trx); + mtr_start(&mtr); btr_pcur_open_on_user_rec(sys_index, tuple, PAGE_CUR_GE, BTR_MODIFY_LEAF, &pcur, &mtr); for (;;) { @@ -3661,7 +3662,7 @@ row_truncate_table_for_mysql( a page in this mini-transaction, and the rest of this loop could latch another index page. */ mtr_commit(&mtr); - mtr_start_trx(&mtr, trx); + mtr_start(&mtr); btr_pcur_restore_position(BTR_MODIFY_LEAF, &pcur, &mtr); } @@ -4003,6 +4004,16 @@ row_drop_table_for_mysql( ut_ad(!table->fts->add_wq); ut_ad(lock_trx_has_sys_table_locks(trx) == 0); + for (;;) { + bool retry = false; + if (dict_fts_index_syncing(table)) { + retry = true; + } + if (!retry) { + break; + } + DICT_BG_YIELD(trx); + } row_mysql_unlock_data_dictionary(trx); fts_optimize_remove_table(table); row_mysql_lock_data_dictionary(trx); diff --git a/storage/xtradb/row/row0quiesce.cc b/storage/xtradb/row/row0quiesce.cc index 6c4e6adb96c..53b4040f74e 100644 --- a/storage/xtradb/row/row0quiesce.cc +++ b/storage/xtradb/row/row0quiesce.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 2012, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2017, MariaDB Corporation. +Copyright (c) 2017, 2018, MariaDB Corporation. 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 @@ -237,7 +237,11 @@ row_quiesce_write_table( mach_write_to_4(ptr, col->len); ptr += sizeof(ib_uint32_t); - mach_write_to_4(ptr, col->mbminmaxlen); + /* FIXME: This will not work if mbminlen>4. + This field is also redundant, because the lengths + are a property of the character set encoding, which + in turn is encodedin prtype above. */ + mach_write_to_4(ptr, col->mbmaxlen * 5 + col->mbminlen); ptr += sizeof(ib_uint32_t); mach_write_to_4(ptr, col->ind); diff --git a/storage/xtradb/row/row0row.cc b/storage/xtradb/row/row0row.cc index 96d25e15777..9bf9e7182ca 100644 --- a/storage/xtradb/row/row0row.cc +++ b/storage/xtradb/row/row0row.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, MariaDB Corporation. 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 @@ -173,7 +174,7 @@ row_build_index_entry_low( /* If a column prefix index, take only the prefix. */ if (ind_field->prefix_len) { len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminmaxlen, + col->prtype, col->mbminlen, col->mbmaxlen, ind_field->prefix_len, len, static_cast<char*>(dfield_get_data(dfield))); dfield_set_len(dfield, len); @@ -588,7 +589,8 @@ row_build_row_ref( dfield_set_len(dfield, dtype_get_at_most_n_mbchars( dtype->prtype, - dtype->mbminmaxlen, + dtype->mbminlen, + dtype->mbmaxlen, clust_col_prefix_len, len, (char*) field)); } @@ -702,7 +704,8 @@ notfound: dfield_set_len(dfield, dtype_get_at_most_n_mbchars( dtype->prtype, - dtype->mbminmaxlen, + dtype->mbminlen, + dtype->mbmaxlen, clust_col_prefix_len, len, (char*) field)); } diff --git a/storage/xtradb/row/row0sel.cc b/storage/xtradb/row/row0sel.cc index 6131129d0a6..03ae6822fb7 100644 --- a/storage/xtradb/row/row0sel.cc +++ b/storage/xtradb/row/row0sel.cc @@ -2,7 +2,7 @@ Copyright (c) 1997, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 2008, Google Inc. -Copyright (c) 2015, 2017, MariaDB Corporation. +Copyright (c) 2015, 2018, MariaDB Corporation. Portions of this file contain modifications contributed and copyrighted by Google, Inc. Those modifications are gratefully acknowledged and are described @@ -98,8 +98,10 @@ row_sel_sec_rec_is_for_blob( /*========================*/ ulint mtype, /*!< in: main type */ ulint prtype, /*!< in: precise type */ - ulint mbminmaxlen, /*!< in: minimum and maximum length of - a multi-byte character */ + ulint mbminlen, /*!< in: minimum length of + a character, in bytes */ + ulint mbmaxlen, /*!< in: maximum length of + a character, in bytes */ const byte* clust_field, /*!< in: the locally stored part of the clustered index column, including the BLOB pointer; the clustered @@ -138,8 +140,7 @@ row_sel_sec_rec_is_for_blob( len = btr_copy_externally_stored_field_prefix(buf, prefix_len, zip_size, - clust_field, clust_len, - NULL); + clust_field, clust_len); if (UNIV_UNLIKELY(len == 0)) { /* The BLOB was being deleted as the server crashed. @@ -150,7 +151,7 @@ row_sel_sec_rec_is_for_blob( return(FALSE); } - len = dtype_get_at_most_n_mbchars(prtype, mbminmaxlen, + len = dtype_get_at_most_n_mbchars(prtype, mbminlen, mbmaxlen, prefix_len, len, (const char*) buf); return(!cmp_data_data(mtype, prtype, buf, len, sec_field, sec_len)); @@ -234,14 +235,14 @@ row_sel_sec_rec_is_for_clust_rec( } len = dtype_get_at_most_n_mbchars( - col->prtype, col->mbminmaxlen, + col->prtype, col->mbminlen, col->mbmaxlen, ifield->prefix_len, len, (char*) clust_field); if (rec_offs_nth_extern(clust_offs, clust_pos) && len < sec_len) { if (!row_sel_sec_rec_is_for_blob( col->mtype, col->prtype, - col->mbminmaxlen, + col->mbminlen, col->mbmaxlen, clust_field, clust_len, sec_field, sec_len, ifield->prefix_len, @@ -458,7 +459,7 @@ row_sel_fetch_columns( data = btr_rec_copy_externally_stored_field( rec, offsets, dict_table_zip_size(index->table), - field_no, &len, heap, NULL); + field_no, &len, heap); /* data == NULL means that the externally stored field was not @@ -1406,7 +1407,7 @@ table_loop: /* Open a cursor to index, or restore an open cursor position */ - mtr_start_trx(&mtr, thr_get_trx(thr)); + mtr_start(&mtr); if (consistent_read && plan->unique_search && !plan->pcur_is_open && !plan->must_get_clust @@ -1447,7 +1448,7 @@ table_loop: plan_reset_cursor(plan); mtr_commit(&mtr); - mtr_start_trx(&mtr, thr_get_trx(thr)); + mtr_start(&mtr); } if (search_latch_locked) { @@ -2828,7 +2829,7 @@ row_sel_store_mysql_field_func( data = btr_rec_copy_externally_stored_field( rec, offsets, dict_table_zip_size(prebuilt->table), - field_no, &len, heap, NULL); + field_no, &len, heap); if (UNIV_UNLIKELY(!data)) { /* The externally stored field was not written @@ -3933,7 +3934,7 @@ row_search_for_mysql( } } - mtr_start_trx(&mtr, trx); + mtr_start(&mtr); /*-------------------------------------------------------------*/ /* PHASE 2: Try fast adaptive hash index search if possible */ @@ -5159,7 +5160,7 @@ next_rec: mtr_commit(&mtr); mtr_has_extra_clust_latch = FALSE; - mtr_start_trx(&mtr, trx); + mtr_start(&mtr); if (sel_restore_position_for_mysql(&same_user_rec, BTR_SEARCH_LEAF, pcur, moves_up, &mtr)) { @@ -5226,7 +5227,7 @@ lock_table_wait: /* It was a lock wait, and it ended */ thr->lock_state = QUE_THR_LOCK_NOLOCK; - mtr_start_trx(&mtr, trx); + mtr_start(&mtr); /* Table lock waited, go try to obtain table lock again */ diff --git a/storage/xtradb/row/row0umod.cc b/storage/xtradb/row/row0umod.cc index 2e5cc14bfe1..bb2fc536616 100644 --- a/storage/xtradb/row/row0umod.cc +++ b/storage/xtradb/row/row0umod.cc @@ -269,7 +269,7 @@ row_undo_mod_clust( pcur = &node->pcur; index = btr_cur_get_index(btr_pcur_get_btr_cur(pcur)); - mtr_start_trx(&mtr, thr_get_trx(thr)); + mtr_start(&mtr); online = dict_index_is_online_ddl(index); if (online) { @@ -298,7 +298,7 @@ row_undo_mod_clust( /* We may have to modify tree structure: do a pessimistic descent down the index tree */ - mtr_start_trx(&mtr, thr_get_trx(thr)); + mtr_start(&mtr); err = row_undo_mod_clust_low( node, &offsets, &offsets_heap, @@ -350,7 +350,7 @@ row_undo_mod_clust( if (err == DB_SUCCESS && node->rec_type == TRX_UNDO_UPD_DEL_REC) { - mtr_start_trx(&mtr, thr_get_trx(thr)); + mtr_start(&mtr); /* It is not necessary to call row_log_table, because the record is delete-marked and would thus @@ -363,7 +363,7 @@ row_undo_mod_clust( /* We may have to modify tree structure: do a pessimistic descent down the index tree */ - mtr_start_trx(&mtr, thr_get_trx(thr)); + mtr_start(&mtr); err = row_undo_mod_remove_clust_low(node, thr, &mtr, BTR_MODIFY_TREE); @@ -410,7 +410,7 @@ row_undo_mod_del_mark_or_remove_sec_low( enum row_search_result search_result; log_free_check(); - mtr_start_trx(&mtr, thr_get_trx(thr)); + mtr_start(&mtr); if (mode == BTR_MODIFY_TREE && index->space == IBUF_SPACE_ID && !dict_index_is_unique(index)) { @@ -471,7 +471,7 @@ row_undo_mod_del_mark_or_remove_sec_low( which cannot be purged yet, requires its existence. If some requires, we should delete mark the record. */ - mtr_start_trx(&mtr_vers, thr_get_trx(thr)); + mtr_start(&mtr_vers); success = btr_pcur_restore_position(BTR_SEARCH_LEAF, &(node->pcur), &mtr_vers); @@ -587,7 +587,7 @@ row_undo_mod_del_unmark_sec_and_undo_update( ut_ad(trx->id); log_free_check(); - mtr_start_trx(&mtr, thr_get_trx(thr)); + mtr_start(&mtr); if (mode == BTR_MODIFY_TREE && index->space == IBUF_SPACE_ID && !dict_index_is_unique(index)) { diff --git a/storage/xtradb/row/row0upd.cc b/storage/xtradb/row/row0upd.cc index 7c6f51f0dd1..1b9f87e233f 100644 --- a/storage/xtradb/row/row0upd.cc +++ b/storage/xtradb/row/row0upd.cc @@ -1,6 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. +Copyright (c) 2018, MariaDB Corporation. 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 @@ -261,7 +262,7 @@ row_upd_check_references_constraints( DEBUG_SYNC_C("foreign_constraint_check_for_update"); - mtr_start_trx(mtr, trx); + mtr_start(mtr); if (trx->dict_operation_lock_mode == 0) { got_s_lock = TRUE; @@ -1155,7 +1156,7 @@ row_upd_ext_fetch( byte* buf = static_cast<byte*>(mem_heap_alloc(heap, *len)); *len = btr_copy_externally_stored_field_prefix( - buf, *len, zip_size, data, local_len, NULL); + buf, *len, zip_size, data, local_len); /* We should never update records containing a half-deleted BLOB. */ ut_a(*len); @@ -1207,7 +1208,7 @@ row_upd_index_replace_new_col_val( } len = dtype_get_at_most_n_mbchars(col->prtype, - col->mbminmaxlen, + col->mbminlen, col->mbmaxlen, field->prefix_len, len, (const char*) data); @@ -1855,7 +1856,7 @@ row_upd_sec_index_entry( } #endif /* UNIV_DEBUG */ - mtr_start_trx(&mtr, trx); + mtr_start(&mtr); if (*index->name == TEMP_INDEX_PREFIX) { /* The index->online_status may change if the @@ -2398,7 +2399,7 @@ row_upd_clust_rec( /* We may have to modify the tree structure: do a pessimistic descent down the index tree */ - mtr_start_trx(mtr, thr_get_trx(thr)); + mtr_start(mtr); /* NOTE: this transaction has an s-lock or x-lock on the record and therefore other transactions cannot modify the record when we have no @@ -2613,7 +2614,7 @@ row_upd_clust_step( /* We have to restore the cursor to its position */ - mtr_start_trx(&mtr, thr_get_trx(thr)); + mtr_start(&mtr); /* If the restoration does not succeed, then the same transaction has deleted the record on which the cursor was, @@ -2686,7 +2687,7 @@ row_upd_clust_step( mtr_commit(&mtr); - mtr_start_trx(&mtr, thr_get_trx(thr)); + mtr_start(&mtr); success = btr_pcur_restore_position(BTR_MODIFY_LEAF, pcur, &mtr); diff --git a/storage/xtradb/srv/srv0srv.cc b/storage/xtradb/srv/srv0srv.cc index ff3581b1c50..e295e502080 100644 --- a/storage/xtradb/srv/srv0srv.cc +++ b/storage/xtradb/srv/srv0srv.cc @@ -82,10 +82,6 @@ Created 10/8/1995 Heikki Tuuri /* prototypes for new functions added to ha_innodb.cc */ ibool innobase_get_slow_log(); -#ifdef WITH_WSREP -extern int wsrep_debug; -extern int wsrep_trx_is_aborting(void *thd_ptr); -#endif /* The following counter is incremented whenever there is some user activity in the server */ UNIV_INTERN ulint srv_activity_count = 0; @@ -479,6 +475,9 @@ UNIV_INTERN my_bool srv_print_all_deadlocks = FALSE; /* Produce a stacktrace on long semaphore wait */ UNIV_INTERN my_bool srv_use_stacktrace = FALSE; +/** Print lock wait timeout info to mysqld stderr */ +my_bool srv_print_lock_wait_timeout_info = FALSE; + /** Enable INFORMATION_SCHEMA.innodb_cmp_per_index */ UNIV_INTERN my_bool srv_cmp_per_index_enabled = FALSE; @@ -2132,6 +2131,9 @@ srv_export_innodb_status(void) scrub_stat.page_split_failures_unknown; } + export_vars.innodb_buffered_aio_submitted = + srv_stats.n_aio_submitted; + mutex_exit(&srv_innodb_monitor_mutex); } diff --git a/storage/xtradb/trx/trx0rec.cc b/storage/xtradb/trx/trx0rec.cc index e295e7e05ca..dc9b0829925 100644 --- a/storage/xtradb/trx/trx0rec.cc +++ b/storage/xtradb/trx/trx0rec.cc @@ -467,7 +467,7 @@ trx_undo_page_fetch_ext( { /* Fetch the BLOB. */ ulint ext_len = btr_copy_externally_stored_field_prefix( - ext_buf, prefix_len, zip_size, field, *len, NULL); + ext_buf, prefix_len, zip_size, field, *len); /* BLOBs should always be nonempty. */ ut_a(ext_len); /* Append the BLOB pointer to the prefix. */ @@ -1268,7 +1268,7 @@ trx_undo_report_row_operation( rseg = trx->rseg; - mtr_start_trx(&mtr, trx); + mtr_start(&mtr); mutex_enter(&trx->undo_mutex); /* If the undo log is not assigned yet, assign one */ @@ -1345,7 +1345,7 @@ trx_undo_report_row_operation( latches, such as SYNC_FSP and SYNC_FSP_PAGE. */ mtr_commit(&mtr); - mtr_start_trx(&mtr, trx); + mtr_start(&mtr); mutex_enter(&rseg->mutex); trx_undo_free_last_page(trx, undo, &mtr); @@ -1382,7 +1382,7 @@ trx_undo_report_row_operation( /* We have to extend the undo log by one page */ ut_ad(++loop_count < 2); - mtr_start_trx(&mtr, trx); + mtr_start(&mtr); /* When we add a page to an undo log, this is analogous to a pessimistic insert in a B-tree, and we must reserve the diff --git a/storage/xtradb/trx/trx0undo.cc b/storage/xtradb/trx/trx0undo.cc index 24d14e06080..0d5a0f55f0d 100644 --- a/storage/xtradb/trx/trx0undo.cc +++ b/storage/xtradb/trx/trx0undo.cc @@ -1070,9 +1070,11 @@ Truncates an undo log from the end. This function is used during a rollback to free space from an undo log. */ UNIV_INTERN void -trx_undo_truncate_end( +trx_undo_truncate_end_func( /*=======================*/ - trx_t* trx, /*!< in: transaction whose undo log it is */ +#ifdef UNIV_DEBUG + const trx_t* trx, /*!< in: transaction whose undo log it is */ +#endif /* UNIV_DEBUG */ trx_undo_t* undo, /*!< in: undo log */ undo_no_t limit) /*!< in: all undo records with undo number >= this value should be truncated */ @@ -1087,7 +1089,7 @@ trx_undo_truncate_end( ut_ad(mutex_own(&(trx->rseg->mutex))); for (;;) { - mtr_start_trx(&mtr, trx); + mtr_start(&mtr); trunc_here = NULL; @@ -1774,7 +1776,7 @@ trx_undo_assign_undo( ut_ad(mutex_own(&(trx->undo_mutex))); - mtr_start_trx(&mtr, trx); + mtr_start(&mtr); mutex_enter(&rseg->mutex); diff --git a/support-files/mariadb.service.in b/support-files/mariadb.service.in index fe00f160d28..ef9fa5c2a22 100644 --- a/support-files/mariadb.service.in +++ b/support-files/mariadb.service.in @@ -87,7 +87,6 @@ ExecStart=@sbindir@/mysqld $MYSQLD_OPTS $_WSREP_NEW_CLUSTER $_WSREP_START_POSITI # Unset _WSREP_START_POSITION environment variable. ExecStartPost=/bin/sh -c "systemctl unset-environment _WSREP_START_POSITION" -KillMode=process KillSignal=SIGTERM # Don't want to see an automated SIGKILL ever diff --git a/support-files/mariadb@.service.in b/support-files/mariadb@.service.in index 000724d7fe2..465a0d94c62 100644 --- a/support-files/mariadb@.service.in +++ b/support-files/mariadb@.service.in @@ -108,7 +108,6 @@ ExecStart=@sbindir@/mysqld --defaults-file=@sysconf2dir@/my%I.cnf \ # Unset _WSREP_START_POSITION environment variable. ExecStartPost=/bin/sh -c "systemctl unset-environment _WSREP_START_POSITION%I" -KillMode=process KillSignal=SIGTERM # Don't want to see an automated SIGKILL ever diff --git a/support-files/mysql.server.sh b/support-files/mysql.server.sh index 1ebf2922279..342929d2ecd 100644 --- a/support-files/mysql.server.sh +++ b/support-files/mysql.server.sh @@ -2,7 +2,7 @@ # Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB # This file is public domain and comes with NO WARRANTY of any kind -# MySQL daemon start/stop script. +# MariaDB daemon start/stop script. # Usually this is put in /etc/init.d (at least on machines SYSV R4 based # systems) and linked to /etc/rc3.d/S99mysql and /etc/rc0.d/K01mysql. @@ -21,14 +21,14 @@ # Required-Stop: $local_fs $network $remote_fs # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 -# Short-Description: start and stop MySQL -# Description: MySQL is a very fast and reliable SQL database engine. +# Short-Description: start and stop MariaDB +# Description: MariaDB is a very fast and reliable SQL database engine. ### END INIT INFO -# If you install MySQL on some other places than @prefix@, then you +# If you install MariaDB on some other places than @prefix@, then you # have to do one of the following things for this script to work: # -# - Run this script from within the MySQL installation directory +# - Run this script from within the MariaDB installation directory # - Create a /etc/my.cnf file with the following information: # [mysqld] # basedir=<path-to-mysql-installation-directory> @@ -37,11 +37,11 @@ # - Add the path to the mysql-installation-directory to the basedir variable # below. # -# If you want to affect other MySQL variables, you should make your changes -# in the /etc/my.cnf, ~/.my.cnf or other MySQL configuration files. +# If you want to affect other MariaDB variables, you should make your changes +# in the /etc/my.cnf, ~/.my.cnf or other MariaDB configuration files. # If you change base dir, you must also change datadir. These may get -# overwritten by settings in the MySQL configuration files. +# overwritten by settings in the MariaDB configuration files. basedir= datadir= @@ -291,7 +291,7 @@ case "$mode" in # Safeguard (relative paths, core dumps..) cd $basedir - echo $echo_n "Starting MySQL" + echo $echo_n "Starting MariaDB" if test -x $bindir/mysqld_safe then # Give extra arguments to mysqld with the my.cnf file. This script @@ -307,7 +307,7 @@ case "$mode" in exit $return_value else - log_failure_msg "Couldn't find MySQL server ($bindir/mysqld_safe)" + log_failure_msg "Couldn't find MariaDB server ($bindir/mysqld_safe)" fi ;; @@ -321,12 +321,12 @@ case "$mode" in if (kill -0 $mysqld_pid 2>/dev/null) then - echo $echo_n "Shutting down MySQL" + echo $echo_n "Shutting down MariaDB" kill $mysqld_pid # mysqld should remove the pid file when it exits, so wait for it. wait_for_gone $mysqld_pid "$mysqld_pid_file_path"; return_value=$? else - log_failure_msg "MySQL server process #$mysqld_pid is not running!" + log_failure_msg "MariaDB server process #$mysqld_pid is not running!" rm "$mysqld_pid_file_path" fi @@ -337,7 +337,7 @@ case "$mode" in fi exit $return_value else - log_failure_msg "MySQL server PID file could not be found!" + log_failure_msg "MariaDB server PID file could not be found!" fi ;; @@ -358,10 +358,10 @@ case "$mode" in 'reload'|'force-reload') if test -s "$mysqld_pid_file_path" ; then read mysqld_pid < "$mysqld_pid_file_path" - kill -HUP $mysqld_pid && log_success_msg "Reloading service MySQL" + kill -HUP $mysqld_pid && log_success_msg "Reloading service MariaDB" touch "$mysqld_pid_file_path" else - log_failure_msg "MySQL PID file could not be found!" + log_failure_msg "MariaDB PID file could not be found!" exit 1 fi ;; @@ -370,10 +370,10 @@ case "$mode" in if test -s "$mysqld_pid_file_path" ; then read mysqld_pid < "$mysqld_pid_file_path" if kill -0 $mysqld_pid 2>/dev/null ; then - log_success_msg "MySQL running ($mysqld_pid)" + log_success_msg "MariaDB running ($mysqld_pid)" exit 0 else - log_failure_msg "MySQL is not running, but PID file exists" + log_failure_msg "MariaDB is not running, but PID file exists" exit 1 fi else @@ -383,17 +383,17 @@ case "$mode" in # test if multiple pids exist pid_count=`echo $mysqld_pid | wc -w` if test $pid_count -gt 1 ; then - log_failure_msg "Multiple MySQL running but PID file could not be found ($mysqld_pid)" + log_failure_msg "Multiple MariaDB running but PID file could not be found ($mysqld_pid)" exit 5 elif test -z $mysqld_pid ; then if test -f "$lock_file_path" ; then - log_failure_msg "MySQL is not running, but lock file ($lock_file_path) exists" + log_failure_msg "MariaDB is not running, but lock file ($lock_file_path) exists" exit 2 fi - log_failure_msg "MySQL is not running" + log_failure_msg "MariaDB is not running" exit 3 else - log_failure_msg "MySQL is running but PID file could not be found" + log_failure_msg "MariaDB is running but PID file could not be found" exit 4 fi fi @@ -401,7 +401,7 @@ case "$mode" in 'configtest') # Safeguard (relative paths, core dumps..) cd $basedir - echo $echo_n "Testing MySQL configuration syntax" + echo $echo_n "Testing MariaDB configuration syntax" daemon=$bindir/mysqld if test -x $libexecdir/mysqld then @@ -439,7 +439,7 @@ case "$mode" in *) # usage basename=`basename "$0"` - echo "Usage: $basename {start|stop|restart|reload|force-reload|status|configtest|bootstrap} [ MySQL server options ]" + echo "Usage: $basename {start|stop|restart|reload|force-reload|status|configtest|bootstrap} [ MariaDB server options ]" exit 1 ;; esac diff --git a/unittest/mysys/base64-t.c b/unittest/mysys/base64-t.c index 58d0014dee1..abbc028917d 100644 --- a/unittest/mysys/base64-t.c +++ b/unittest/mysys/base64-t.c @@ -90,6 +90,9 @@ main(int argc __attribute__((unused)),char *argv[]) diag("src length: %.8x, dst length: %.8x\n", (uint) src_len, (uint) dst_len); } + free(dst); + free(str); + free(src); } my_end(0); return exit_status(); diff --git a/win/packaging/WixUIBannerBmp.jpg b/win/packaging/WixUIBannerBmp.jpg Binary files differindex a04177bed9d..66256b79255 100644 --- a/win/packaging/WixUIBannerBmp.jpg +++ b/win/packaging/WixUIBannerBmp.jpg diff --git a/win/packaging/WixUIDialogBmp.jpg b/win/packaging/WixUIDialogBmp.jpg Binary files differindex 466cdc461c8..c6ddf12bd2a 100644 --- a/win/packaging/WixUIDialogBmp.jpg +++ b/win/packaging/WixUIDialogBmp.jpg |