diff options
author | Seppo Jaakola <seppo.jaakola@codership.com> | 2013-07-13 13:01:13 +0300 |
---|---|---|
committer | Seppo Jaakola <seppo.jaakola@codership.com> | 2013-07-13 13:01:13 +0300 |
commit | 0a9216835f406947fb4d492616da4cda75e5e113 (patch) | |
tree | 7fbf5059c59fa86ca255452f3ce312aece492652 | |
parent | 58926b5e1990d3245b55081ba511fbabe2604e17 (diff) | |
download | mariadb-git-0a9216835f406947fb4d492616da4cda75e5e113.tar.gz |
Initial merge result with mariaDB 10: lp:maria
160 files changed, 9799 insertions, 938 deletions
diff --git a/.bzrignore b/.bzrignore index 457e90537fd..6939ce594c5 100644 --- a/.bzrignore +++ b/.bzrignore @@ -970,6 +970,8 @@ support-files/mysql.server support-files/mysql.spec support-files/mysqld_multi.server support-files/ndb-config-2-node.ini +support-files/wsrep.cnf +support-files/wsrep_notify TAGS test/ndbapi/bank/bankCreator test/ndbapi/bank/bankMakeGL @@ -1093,6 +1095,9 @@ sql/share/slovak sql/share/spanish sql/share/swedish sql/share/ukrainian +scripts/wsrep_sst_mysqldump +scripts/wsrep_sst_rsync +scripts/wsrep_sst_xtrabackup CPackConfig.cmake CPackSourceConfig.cmake Docs/INFO_BIN diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index a4853c823ab..502361c6fff 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -215,7 +215,7 @@ all_configs="$SSL_LIBRARY --with-plugins=max --with-plugin-ndbcluster --with-emb alpha_cflags="$check_cpu_cflags -Wa,-m$cpu_flag" amd64_cflags="$check_cpu_cflags" amd64_cxxflags="" # If dropping '--with-big-tables', add here "-DBIG_TABLES" -pentium_cflags="$check_cpu_cflags" +pentium_cflags="$check_cpu_cflags -m32" pentium64_cflags="$check_cpu_cflags -m64" ppc_cflags="$check_cpu_cflags" sparc_cflags="" diff --git a/CMakeLists.txt b/CMakeLists.txt index 19f951c7589..e8a48cbb5e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -148,6 +148,7 @@ INCLUDE(ctest) INCLUDE(plugin) INCLUDE(install_macros) INCLUDE(mysql_add_executable) +INCLUDE(wsrep) # Handle options OPTION(DISABLE_SHARED @@ -187,6 +188,12 @@ MARK_AS_ADVANCED(ENABLED_LOCAL_INFILE) OPTION(WITH_FAST_MUTEXES "Compile with fast mutexes" OFF) MARK_AS_ADVANCED(WITH_FAST_MUTEXES) +OPTION(WITH_INNODB_DISALLOW_WRITES "InnoDB freeze writes patch from Google" ${WITH_WSREP}) +IF (WITH_INNODB_DISALLOW_WRITES) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWITH_INNODB_DISALLOW_WRITES") + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DWITH_INNODB_DISALLOW_WRITES") +ENDIF() + # Set DBUG_OFF and other optional release-only flags for non-debug project types FOREACH(BUILD_TYPE RELEASE RELWITHDEBINFO MINSIZEREL) FOREACH(LANG C CXX) @@ -298,6 +305,9 @@ ADD_SUBDIRECTORY(vio) ADD_SUBDIRECTORY(regex) ADD_SUBDIRECTORY(mysys) ADD_SUBDIRECTORY(libmysql) +IF(WITH_WSREP) +ADD_SUBDIRECTORY(wsrep) +ENDIF() ADD_SUBDIRECTORY(client) ADD_SUBDIRECTORY(extra) ADD_SUBDIRECTORY(libservices) @@ -381,7 +391,7 @@ OPTIONAL INSTALL(FILES README DESTINATION ${INSTALL_DOCREADMEDIR} COMPONENT Readme) INSTALL(FILES ${CMAKE_BINARY_DIR}/Docs/INFO_SRC ${CMAKE_BINARY_DIR}/Docs/INFO_BIN DESTINATION ${INSTALL_DOCDIR}) IF(UNIX) - INSTALL(FILES Docs/INSTALL-BINARY DESTINATION ${INSTALL_DOCREADMEDIR} COMPONENT Readme) + INSTALL(FILES Docs/INSTALL-BINARY Docs/README-wsrep DESTINATION ${INSTALL_DOCREADMEDIR} COMPONENT Readme) ENDIF() INCLUDE(CPack) @@ -1,4 +1,57 @@ -This is a release of MariaDB. +This is a release of MariaDB Galera Cluster. + + * https://kb.askmonty.org/en/galera/ + * https://kb.askmonty.org/en/what-is-mariadb-galera-cluster/ + +MariaDB Galera Cluster is a synchronous multi-master cluster for MariaDB. + +Features: + + * Synchronous replication + * Active-active multi-master topology + * Read and write to any cluster node + * Automatic membership control, failed nodes drop from the cluster + * Automatic node joining + * True parallel replication, on row level + * Direct client connections, native MySQL look & feel + +Benefits: + +The above features yield several benefits for a DBMS clustering solution, +including: + +* No slave lag +* No lost transactions +* Both read and write scalability +* Smaller client latencies +* Technology + +MariaDB Galera Cluster uses the Galera library for the replication +implementation. To interface with Galera replication, we have enhanced MariaDB +to support the replication API definition in the wsrep API project. + + * http://codership.com/products/galera_replication + * https://launchpad.net/wsrep + +The implementation of the replication API in MariaDB happens in the open source +MySQL-wsrep project. + + * http://www.codership.com/products/mysql-write-set-replication-project + +See Also: + +* About Galera Replication: + https://kb.askmonty.org/en/about-galera-replication/ +* Codership: Using Galera Cluster: + http://codership.com/content/using-galera-cluster +* Galera Use Cases: + https://kb.askmonty.org/en/galera-use-cases/ +* Getting Started with MariaDB Galera Cluster: + https://kb.askmonty.org/en/getting-started-with-mariadb-galera-cluster/ + +*************************************************************************** + +About MariaDB MariaDB is designed as a drop-in replacement of MySQL(R) with more features, new storage engines, fewer bugs, and better performance. diff --git a/cmake/configure.pl b/cmake/configure.pl index 51e83c2815c..d39071b13bb 100644 --- a/cmake/configure.pl +++ b/cmake/configure.pl @@ -206,6 +206,16 @@ foreach my $option (@ARGV) $cmakeargs = $cmakeargs." -DMYSQL_DATADIR=".substr($option,14); next; } + if ($option =~ /layout=/) + { + $cmakeargs = $cmakeargs." -DINSTALL_LAYOUT=".substr($option,7); + next; + } + if ($option =~ /with-unix-socket-path=/) + { + $cmakeargs = $cmakeargs." -DMYSQL_UNIX_ADDR=".substr($option,22); + next; + } if ($option =~ /mysql-maintainer-mode/) { $cmakeargs = $cmakeargs." -DMYSQL_MAINTAINER_MODE=" . diff --git a/cmake/cpack_rpm.cmake b/cmake/cpack_rpm.cmake index ee7c4af7155..e7da4e984e0 100644 --- a/cmake/cpack_rpm.cmake +++ b/cmake/cpack_rpm.cmake @@ -23,11 +23,9 @@ SET(CPACK_COMPONENT_SHAREDLIBRARIES_GROUP "shared") SET(CPACK_COMPONENT_COMMON_GROUP "common") SET(CPACK_COMPONENT_COMPAT_GROUP "compat") SET(CPACK_COMPONENTS_ALL Server ManPagesServer IniFiles Server_Scripts - SupportFiles Development ManPagesDevelopment - ManPagesTest Readme ManPagesClient Test - Common Client SharedLibraries) + SupportFiles Readme) -SET(CPACK_RPM_PACKAGE_NAME "MariaDB") +SET(CPACK_RPM_PACKAGE_NAME "MariaDB-Galera") SET(CPACK_PACKAGE_FILE_NAME "${CPACK_RPM_PACKAGE_NAME}-${VERSION}-${RPM}-${CMAKE_SYSTEM_PROCESSOR}") SET(CPACK_RPM_PACKAGE_RELEASE 1) # FIX: add distribution name here @@ -124,32 +122,6 @@ SET(CPACK_RPM_test_PACKAGE_PROVIDES "MariaDB-test MySQL-test mysql-test") # workaround for lots of perl dependencies added by rpmbuild SET(CPACK_RPM_test_PACKAGE_PROVIDES "${CPACK_RPM_test_PACKAGE_PROVIDES} perl(lib::mtr_gcov.pl) perl(lib::mtr_gprof.pl) perl(lib::mtr_io.pl) perl(lib::mtr_misc.pl) perl(lib::mtr_process.pl) perl(lib::v1/mtr_cases.pl) perl(lib::v1/mtr_gcov.pl) perl(lib::v1/mtr_gprof.pl) perl(lib::v1/mtr_im.pl) perl(lib::v1/mtr_io.pl) perl(lib::v1/mtr_match.pl) perl(lib::v1/mtr_misc.pl) perl(lib::v1/mtr_process.pl) perl(lib::v1/mtr_report.pl) perl(lib::v1/mtr_stress.pl) perl(lib::v1/mtr_timer.pl) perl(lib::v1/mtr_unique.pl) perl(mtr_cases) perl(mtr_io.pl) perl(mtr_match) perl(mtr_misc.pl) perl(mtr_report) perl(mtr_results) perl(mtr_unique)") -# If we want to build build MariaDB-shared-compat, -# extract compat libraries from MariaDB-shared-5.3 rpm -FILE(GLOB compat_rpm RELATIVE ${CMAKE_SOURCE_DIR} - "${CMAKE_SOURCE_DIR}/../MariaDB-shared-5.3.*.rpm") -IF (compat_rpm) - MESSAGE("Using ${compat_rpm} to build MariaDB-compat") - INSTALL(CODE "EXECUTE_PROCESS( - COMMAND rpm2cpio ${CMAKE_SOURCE_DIR}/${compat_rpm} - COMMAND cpio --extract --make-directories */libmysqlclient*.so.* - - WORKING_DIRECTORY \$ENV{DESTDIR}) - EXECUTE_PROCESS( - COMMAND chmod -R a+rX . - WORKING_DIRECTORY \$ENV{DESTDIR})" - COMPONENT Compat) - SET(CPACK_COMPONENTS_ALL ${CPACK_COMPONENTS_ALL} Compat) - - # RHEL6/CentOS6 install Postfix by default, and it requires - # libmysqlclient.so.16 that pulls in mysql-libs-5.1.x - # And the latter conflicts with our rpms. - # Make sure that for these distribuions all our rpms require - # MariaDB-compat, that will replace mysql-libs-5.1 - IF(RPM MATCHES "(rhel|centos)6") - SET(CPACK_RPM_common_PACKAGE_REQUIRES "MariaDB-compat") - ENDIF() -ENDIF(compat_rpm) - SET(CPACK_RPM_compat_PACKAGE_REQUIRES "/bin/sh") # to mask CPACK_RPM_PACKAGE_REQUIRES SET(CPACK_RPM_compat_PACKAGE_PROVIDES "mysql-libs = 5.3.5") # exact version doesn't matter as long as it greater than 5.1 SET(CPACK_RPM_compat_PACKAGE_OBSOLETES "mysql-libs < 5.3.5") diff --git a/cmake/package_name.cmake b/cmake/package_name.cmake index 93e7d968b2a..df6822493cb 100644 --- a/cmake/package_name.cmake +++ b/cmake/package_name.cmake @@ -120,7 +120,7 @@ IF(NOT VERSION) ELSEIF(MYSQL_SERVER_SUFFIX) SET(PRODUCT_TAG "${MYSQL_SERVER_SUFFIX}") # Already has a leading dash ELSE() - SET(PRODUCT_TAG) + SET(PRODUCT_TAG "-galera") ENDIF() IF("${VERSION}" MATCHES "-ndb-") diff --git a/debian/dist/Debian/mariadb-server-10.0.dirs b/debian/dist/Debian/mariadb-server-10.0.dirs index 320299b17ca..4eef28f62e1 100644 --- a/debian/dist/Debian/mariadb-server-10.0.dirs +++ b/debian/dist/Debian/mariadb-server-10.0.dirs @@ -6,5 +6,6 @@ usr/sbin usr/share/man/man8 usr/share/mysql usr/share/doc/mariadb-server-10.0 +usr/support-files var/run/mysqld var/lib/mysql-upgrade diff --git a/debian/dist/Debian/rules b/debian/dist/Debian/rules index 6de5c6603dc..617bb2ddedf 100755 --- a/debian/dist/Debian/rules +++ b/debian/dist/Debian/rules @@ -190,15 +190,13 @@ install: build # lintian overrides mkdir -p $(TMP)/usr/share/lintian/overrides/ - cp debian/mysql-common.lintian-overrides $(TMP)/usr/share/lintian/overrides/mysql-common - cp debian/mariadb-server-10.0.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-server-10.0 - cp debian/mariadb-client-10.0.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-client-10.0 + cp debian/mariadb-galera-server-10.0.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-server-10.0 # For 5.0 -> 10.0 transition d=$(TMP)/usr/share/mysql-common/internal-use-only/; \ mkdir -p $$d; \ - cp debian/mariadb-server-10.0.mysql.init $$d/_etc_init.d_mysql; \ - cp debian/mariadb-server-10.0.mysql-server.logrotate $$d/_etc_logrotate.d_mysql-server; \ + cp debian/mariadb-galera-server-10.0.mysql.init $$d/_etc_init.d_mysql; \ + cp debian/mariadb-galera-server-10.0.mysql-server.logrotate $$d/_etc_logrotate.d_mysql-server; \ cp debian/additions/debian-start $$d/_etc_mysql_debian-start; dh_movefiles diff --git a/debian/dist/Ubuntu/mariadb-server-10.0.dirs b/debian/dist/Ubuntu/mariadb-server-10.0.dirs index 320299b17ca..4eef28f62e1 100644 --- a/debian/dist/Ubuntu/mariadb-server-10.0.dirs +++ b/debian/dist/Ubuntu/mariadb-server-10.0.dirs @@ -6,5 +6,6 @@ usr/sbin usr/share/man/man8 usr/share/mysql usr/share/doc/mariadb-server-10.0 +usr/support-files var/run/mysqld var/lib/mysql-upgrade diff --git a/debian/dist/Ubuntu/rules b/debian/dist/Ubuntu/rules index 739cd91dcd8..ea138f8b640 100755 --- a/debian/dist/Ubuntu/rules +++ b/debian/dist/Ubuntu/rules @@ -190,15 +190,13 @@ install: build # lintian overrides mkdir -p $(TMP)/usr/share/lintian/overrides/ - cp debian/mysql-common.lintian-overrides $(TMP)/usr/share/lintian/overrides/mysql-common - cp debian/mariadb-server-10.0.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-server-10.0 - cp debian/mariadb-client-10.0.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-client-10.0 + cp debian/mariadb-galera-server-10.0.lintian-overrides $(TMP)/usr/share/lintian/overrides/mariadb-server-10.0 # For 5.0 -> 10.0 transition d=$(TMP)/usr/share/mysql-common/internal-use-only/; \ mkdir -p $$d; \ - cp debian/mariadb-server-10.0.mysql.init $$d/_etc_init.d_mysql; \ - cp debian/mariadb-server-10.0.mysql-server.logrotate $$d/_etc_logrotate.d_mysql-server; \ + cp debian/mariadb-galera-server-10.0.mysql.init $$d/_etc_init.d_mysql; \ + cp debian/mariadb-galera-server-10.0.mysql-server.logrotate $$d/_etc_logrotate.d_mysql-server; \ cp debian/additions/debian-start $$d/_etc_mysql_debian-start; # install AppArmor profile diff --git a/debian/libmariadbclient-dev.README.Maintainer b/debian/libmariadbclient-dev.README.Maintainer deleted file mode 100644 index f24cdcd519d..00000000000 --- a/debian/libmariadbclient-dev.README.Maintainer +++ /dev/null @@ -1,4 +0,0 @@ -The examples directory includes files that might be needed by some -developers: -- header files not installed by default -- the example file udf_example.c diff --git a/debian/libmariadbclient-dev.dirs b/debian/libmariadbclient-dev.dirs deleted file mode 100644 index f6ad2870431..00000000000 --- a/debian/libmariadbclient-dev.dirs +++ /dev/null @@ -1,2 +0,0 @@ -usr/include/ -usr/lib/ diff --git a/debian/libmariadbclient-dev.examples b/debian/libmariadbclient-dev.examples deleted file mode 100644 index f1649c311c4..00000000000 --- a/debian/libmariadbclient-dev.examples +++ /dev/null @@ -1 +0,0 @@ -sql/udf_example.c diff --git a/debian/libmariadbclient-dev.files b/debian/libmariadbclient-dev.files deleted file mode 100644 index 8f56a3065d5..00000000000 --- a/debian/libmariadbclient-dev.files +++ /dev/null @@ -1,7 +0,0 @@ -usr/bin/mysql_config -usr/include/mysql -usr/lib/libmysqlclient.a -usr/lib/libmysqlclient_r.a -usr/lib/libmysqlservices.a -usr/share/aclocal/mysql.m4 -usr/share/man/man1/mysql_config.1 diff --git a/debian/libmariadbclient-dev.links b/debian/libmariadbclient-dev.links deleted file mode 100644 index 0076791dcfa..00000000000 --- a/debian/libmariadbclient-dev.links +++ /dev/null @@ -1,2 +0,0 @@ -usr/lib/libmysqlclient.so.18 usr/lib/libmysqlclient.so -usr/lib/libmysqlclient_r.so.18 usr/lib/libmysqlclient_r.so diff --git a/debian/libmariadbclient18.dirs b/debian/libmariadbclient18.dirs deleted file mode 100644 index 2964de6141b..00000000000 --- a/debian/libmariadbclient18.dirs +++ /dev/null @@ -1 +0,0 @@ -usr/lib/ diff --git a/debian/libmariadbclient18.files b/debian/libmariadbclient18.files deleted file mode 100644 index 5162b7b9639..00000000000 --- a/debian/libmariadbclient18.files +++ /dev/null @@ -1 +0,0 @@ -usr/lib/libmysqlclient*.so.* diff --git a/debian/libmariadbclient18.postinst b/debian/libmariadbclient18.postinst deleted file mode 100644 index 29d3b86f978..00000000000 --- a/debian/libmariadbclient18.postinst +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -e - -# dh_installdeb will replace this with shell code automatically -# generated by other debhelper scripts. - -#DEBHELPER# - -exit 0 - -# vim: ts=4 - - diff --git a/debian/libmariadbd-dev.files b/debian/libmariadbd-dev.files deleted file mode 100644 index 26cb8d0a606..00000000000 --- a/debian/libmariadbd-dev.files +++ /dev/null @@ -1,2 +0,0 @@ -usr/lib/mysql/*.a -usr/lib/mysql/*.la diff --git a/debian/mariadb-client-10.0.README.Debian b/debian/mariadb-client-10.0.README.Debian deleted file mode 100644 index b245638f9c9..00000000000 --- a/debian/mariadb-client-10.0.README.Debian +++ /dev/null @@ -1,4 +0,0 @@ -FAQ: - -Q: My <tab> completition is gone, why? -A: You have "no-auto-rehash" in the "[mysql]" section of /etc/mysql/my.cnf! diff --git a/debian/mariadb-client-10.0.dirs b/debian/mariadb-client-10.0.dirs deleted file mode 100644 index ceda5922c5d..00000000000 --- a/debian/mariadb-client-10.0.dirs +++ /dev/null @@ -1,3 +0,0 @@ -usr/bin/ -usr/share/man/man1/ -usr/share/perl5/ diff --git a/debian/mariadb-client-10.0.docs b/debian/mariadb-client-10.0.docs deleted file mode 100644 index 21446855f51..00000000000 --- a/debian/mariadb-client-10.0.docs +++ /dev/null @@ -1,2 +0,0 @@ -debian/additions/innotop/changelog.innotop -README diff --git a/debian/mariadb-client-10.0.files b/debian/mariadb-client-10.0.files deleted file mode 100644 index ac68079718e..00000000000 --- a/debian/mariadb-client-10.0.files +++ /dev/null @@ -1,31 +0,0 @@ -usr/bin/innochecksum -usr/bin/innotop -usr/bin/mysqlaccess -usr/bin/mysqladmin -usr/bin/mysqlbug -usr/bin/mysqldump -usr/bin/mysqldumpslow -usr/bin/mysql_find_rows -usr/bin/mysql_fix_extensions -usr/bin/mysqlimport -usr/bin/mysqlreport -usr/bin/mysqlshow -usr/bin/mysqlslap -usr/bin/mysql_waitpid -usr/share/lintian/overrides/mariadb-client-10.0 -usr/share/man/man1/innotop.1 -usr/share/man/man1/mysqlaccess.1 -usr/share/man/man1/mysqladmin.1 -usr/share/man/man1/mysqlbug.1 -usr/share/man/man1/mysqldump.1 -usr/share/man/man1/mysqldumpslow.1 -usr/share/man/man1/mysql_find_rows.1 -usr/share/man/man1/mysql_fix_extensions.1 -usr/share/man/man1/mysqlimport.1 -usr/share/man/man1/mysqlman.1 -usr/share/man/man1/mysqlreport.1 -usr/share/man/man1/mysqlshow.1 -usr/share/man/man1/mysqlslap.1 -usr/share/man/man1/mysql_tableinfo.1 -usr/share/man/man1/mysql_waitpid.1 -usr/share/man/man8/mysqlmanager.8 diff --git a/debian/mariadb-client-10.0.links b/debian/mariadb-client-10.0.links deleted file mode 100644 index 247369fa218..00000000000 --- a/debian/mariadb-client-10.0.links +++ /dev/null @@ -1,3 +0,0 @@ -usr/bin/mysqlcheck usr/bin/mysqlrepair -usr/bin/mysqlcheck usr/bin/mysqlanalyze -usr/bin/mysqlcheck usr/bin/mysqloptimize diff --git a/debian/mariadb-client-10.0.lintian-overrides b/debian/mariadb-client-10.0.lintian-overrides deleted file mode 100644 index d4dc1a70b1e..00000000000 --- a/debian/mariadb-client-10.0.lintian-overrides +++ /dev/null @@ -1,3 +0,0 @@ -mariadb-client-5.3: package-has-a-duplicate-relation -mariadb-client-5.3: wrong-name-for-upstream-changelog usr/share/doc/mariadb-client-5.3/changelog.innotop.gz -mariadb-client-5.3: pkg-not-in-package-test innotop diff --git a/debian/mariadb-client-10.0.menu b/debian/mariadb-client-10.0.menu deleted file mode 100644 index 1378555c423..00000000000 --- a/debian/mariadb-client-10.0.menu +++ /dev/null @@ -1,3 +0,0 @@ -# According to /usr/share/menu/ policy 1.4, not /usr/share/doc/debian-policy/ -?package(innotop):needs="text" section="Applications/Data Management"\ - title="innotop" command="/usr/bin/innotop" diff --git a/debian/mariadb-client-core-10.0.files b/debian/mariadb-client-core-10.0.files deleted file mode 100644 index a2781309439..00000000000 --- a/debian/mariadb-client-core-10.0.files +++ /dev/null @@ -1,4 +0,0 @@ -usr/bin/mysql -usr/bin/mysqlcheck -usr/share/man/man1/mysql.1 -usr/share/man/man1/mysqlcheck.1 diff --git a/debian/mariadb-common.files b/debian/mariadb-common.files deleted file mode 100644 index f37e46c45fe..00000000000 --- a/debian/mariadb-common.files +++ /dev/null @@ -1 +0,0 @@ -etc/mysql/conf.d/mariadb.cnf diff --git a/debian/mariadb-common.postrm b/debian/mariadb-common.postrm deleted file mode 100644 index 027592f816e..00000000000 --- a/debian/mariadb-common.postrm +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -e - -if [ "$1" = "purge" ]; then - rmdir /etc/mysql/conf.d 2>/dev/null || true - rmdir /etc/mysql 2>/dev/null || true -fi - -#DEBHELPER# diff --git a/debian/mariadb-server-10.0.lintian-overrides b/debian/mariadb-server-10.0.lintian-overrides index ea67ed9de2b..0b2eb6a6496 100644 --- a/debian/mariadb-server-10.0.lintian-overrides +++ b/debian/mariadb-server-10.0.lintian-overrides @@ -1,5 +1,5 @@ -mariadb-server-10.0: command-with-path-in-maintainer-script postinst -mariadb-server-10.0: possible-bashism-in-maintainer-script postinst:81 'p{("a".."z","A".."Z",0..9)[int(rand(62))]}' -mariadb-server-10.0: possible-bashism-in-maintainer-script preinst:33 '${cmd/ */}' -mariadb-server-10.0: statically-linked-binary ./usr/bin/mysql_tzinfo_to_sql -mariadb-server-10.0: statically-linked-binary ./usr/sbin/mysqld +mariadb-galera-server-10.0: command-with-path-in-maintainer-script postinst +mariadb-galera-server-10.0: possible-bashism-in-maintainer-script postinst:81 'p{("a".."z","A".."Z",0..9)[int(rand(62))]}' +mariadb-galera-server-10.0: possible-bashism-in-maintainer-script preinst:33 '${cmd/ */}' +mariadb-galera-server-10.0: statically-linked-binary ./usr/bin/mysql_tzinfo_to_sql +mariadb-galera-server-10.0: statically-linked-binary ./usr/sbin/mysqld diff --git a/debian/mariadb-server-core-10.0.files b/debian/mariadb-server-core-10.0.files deleted file mode 100644 index 5c60ca5ec67..00000000000 --- a/debian/mariadb-server-core-10.0.files +++ /dev/null @@ -1,26 +0,0 @@ -usr/sbin/mysqld -usr/share/man/man8/mysqld.8 -usr/share/mysql/charsets -usr/share/mysql/czech -usr/share/mysql/danish -usr/share/mysql/dutch -usr/share/mysql/english -usr/share/mysql/estonian -usr/share/mysql/french -usr/share/mysql/german -usr/share/mysql/greek -usr/share/mysql/hungarian -usr/share/mysql/italian -usr/share/mysql/japanese -usr/share/mysql/korean -usr/share/mysql/norwegian -usr/share/mysql/norwegian-ny -usr/share/mysql/polish -usr/share/mysql/portuguese -usr/share/mysql/romanian -usr/share/mysql/russian -usr/share/mysql/serbian -usr/share/mysql/slovak -usr/share/mysql/spanish -usr/share/mysql/swedish -usr/share/mysql/ukrainian diff --git a/debian/mariadb-test-10.0.dirs b/debian/mariadb-test-10.0.dirs deleted file mode 100644 index 2c10b45efba..00000000000 --- a/debian/mariadb-test-10.0.dirs +++ /dev/null @@ -1,98 +0,0 @@ -usr/bin -usr/share/man/man1 -usr/share/mysql/mysql-test -usr/share/mysql/mysql-test/extra -usr/share/mysql/mysql-test/extra/binlog_tests -usr/share/mysql/mysql-test/extra/rpl_tests -usr/share/mysql/mysql-test/lib -usr/share/mysql/mysql-test/lib/My -usr/share/mysql/mysql-test/lib/My/SafeProcess -usr/share/mysql/mysql-test/lib/My/File -usr/share/mysql/mysql-test/lib/v1 -usr/share/mysql/mysql-test/lib/v1/My -usr/share/mysql/mysql-test/collections -usr/share/mysql/mysql-test/t -usr/share/mysql/mysql-test/r -usr/share/mysql/mysql-test/include -usr/share/mysql/mysql-test/suite -usr/share/mysql/mysql-test/suite/parts -usr/share/mysql/mysql-test/suite/parts/inc -usr/share/mysql/mysql-test/suite/parts/t -usr/share/mysql/mysql-test/suite/parts/r -usr/share/mysql/mysql-test/suite/rpl_ndb -usr/share/mysql/mysql-test/suite/rpl_ndb/t -usr/share/mysql/mysql-test/suite/rpl_ndb/r -usr/share/mysql/mysql-test/suite/bugs -usr/share/mysql/mysql-test/suite/bugs/t -usr/share/mysql/mysql-test/suite/bugs/r -usr/share/mysql/mysql-test/suite/bugs/data -usr/share/mysql/mysql-test/suite/rpl -usr/share/mysql/mysql-test/suite/rpl/t -usr/share/mysql/mysql-test/suite/rpl/r -usr/share/mysql/mysql-test/suite/rpl/include -usr/share/mysql/mysql-test/suite/innodb -usr/share/mysql/mysql-test/suite/innodb/t -usr/share/mysql/mysql-test/suite/innodb/r -usr/share/mysql/mysql-test/suite/innodb/include -usr/share/mysql/mysql-test/suite/manual -usr/share/mysql/mysql-test/suite/manual/t -usr/share/mysql/mysql-test/suite/manual/r -usr/share/mysql/mysql-test/suite/stress -usr/share/mysql/mysql-test/suite/stress/t -usr/share/mysql/mysql-test/suite/stress/r -usr/share/mysql/mysql-test/suite/stress/include -usr/share/mysql/mysql-test/suite/jp -usr/share/mysql/mysql-test/suite/jp/t -usr/share/mysql/mysql-test/suite/jp/r -usr/share/mysql/mysql-test/suite/jp/include -usr/share/mysql/mysql-test/suite/jp/std_data -usr/share/mysql/mysql-test/suite/ndb -usr/share/mysql/mysql-test/suite/ndb/t -usr/share/mysql/mysql-test/suite/ndb/r -usr/share/mysql/mysql-test/suite/maria -usr/share/mysql/mysql-test/suite/maria/t -usr/share/mysql/mysql-test/suite/maria/r -usr/share/mysql/mysql-test/suite/funcs_2 -usr/share/mysql/mysql-test/suite/funcs_2/lib -usr/share/mysql/mysql-test/suite/funcs_2/t -usr/share/mysql/mysql-test/suite/funcs_2/charset -usr/share/mysql/mysql-test/suite/funcs_2/r -usr/share/mysql/mysql-test/suite/funcs_2/include -usr/share/mysql/mysql-test/suite/funcs_2/data -usr/share/mysql/mysql-test/suite/binlog -usr/share/mysql/mysql-test/suite/binlog/t -usr/share/mysql/mysql-test/suite/binlog/r -usr/share/mysql/mysql-test/suite/binlog/std_data -usr/share/mysql/mysql-test/suite/ndb_team -usr/share/mysql/mysql-test/suite/ndb_team/t -usr/share/mysql/mysql-test/suite/ndb_team/r -usr/share/mysql/mysql-test/suite/federated -usr/share/mysql/mysql-test/suite/pbxt -usr/share/mysql/mysql-test/suite/pbxt/t -usr/share/mysql/mysql-test/suite/pbxt/r -usr/share/mysql/mysql-test/suite/funcs_1 -usr/share/mysql/mysql-test/suite/funcs_1/cursors -usr/share/mysql/mysql-test/suite/funcs_1/bitdata -usr/share/mysql/mysql-test/suite/funcs_1/views -usr/share/mysql/mysql-test/suite/funcs_1/storedproc -usr/share/mysql/mysql-test/suite/funcs_1/triggers -usr/share/mysql/mysql-test/suite/funcs_1/lib -usr/share/mysql/mysql-test/suite/funcs_1/t -usr/share/mysql/mysql-test/suite/funcs_1/r -usr/share/mysql/mysql-test/suite/funcs_1/include -usr/share/mysql/mysql-test/suite/funcs_1/datadict -usr/share/mysql/mysql-test/suite/vcol -usr/share/mysql/mysql-test/suite/vcol/inc -usr/share/mysql/mysql-test/suite/vcol/t -usr/share/mysql/mysql-test/suite/vcol/r -usr/share/mysql/mysql-test/suite/oqgraph -usr/share/mysql/mysql-test/suite/oqgraph/t -usr/share/mysql/mysql-test/suite/oqgraph/r -usr/share/mysql/mysql-test/suite/oqgraph/include -usr/share/mysql/mysql-test/std_data -usr/share/mysql/mysql-test/std_data/ndb_backup50 -usr/share/mysql/mysql-test/std_data/parts -usr/share/mysql/mysql-test/std_data/ndb_backup51_data_le -usr/share/mysql/mysql-test/std_data/ndb_backup51_data_be -usr/share/mysql/mysql-test/std_data/ndb_backup51 -usr/share/mysql/mysql-test/std_data/funcs_1 diff --git a/debian/mariadb-test-10.0.files b/debian/mariadb-test-10.0.files deleted file mode 100644 index ac4fc1c4fca..00000000000 --- a/debian/mariadb-test-10.0.files +++ /dev/null @@ -1,9 +0,0 @@ -usr/bin/mysql_client_test -usr/bin/mysql_client_test_embedded -usr/bin/mysqltest_embedded -usr/share/man/man1/mysql_client_test.1 -usr/share/man/man1/mysql_client_test_embedded.1 -usr/bin/mysqltest -usr/share/man/man1/mysqltest.1 -usr/share/man/man1/mysqltest_embedded.1 -usr/share/mysql/mysql-test diff --git a/debian/mariadb-test-10.0.links b/debian/mariadb-test-10.0.links deleted file mode 100644 index 082680fe5ed..00000000000 --- a/debian/mariadb-test-10.0.links +++ /dev/null @@ -1,2 +0,0 @@ -usr/share/mysql/mysql-test/mysql-test-run.pl usr/share/mysql/mysql-test/mysql-test-run -usr/share/mysql/mysql-test/mysql-test-run.pl usr/share/mysql/mysql-test/mtr diff --git a/debian/mysql-common.dirs b/debian/mysql-common.dirs deleted file mode 100644 index a5a88ede9c1..00000000000 --- a/debian/mysql-common.dirs +++ /dev/null @@ -1 +0,0 @@ -etc/mysql/conf.d/ diff --git a/debian/mysql-common.files b/debian/mysql-common.files deleted file mode 100644 index d167569e892..00000000000 --- a/debian/mysql-common.files +++ /dev/null @@ -1,3 +0,0 @@ -etc/mysql/my.cnf -usr/share/mysql-common/internal-use-only -usr/share/lintian/overrides/mysql-common diff --git a/debian/mysql-common.lintian-overrides b/debian/mysql-common.lintian-overrides deleted file mode 100644 index c6c60ccdc71..00000000000 --- a/debian/mysql-common.lintian-overrides +++ /dev/null @@ -1,2 +0,0 @@ -script-not-executable ./usr/share/mysql-common/internal-use-only/_etc_init.d_mysql -script-not-executable ./usr/share/mysql-common/internal-use-only/_etc_mysql_debian-start diff --git a/debian/mysql-common.postrm b/debian/mysql-common.postrm deleted file mode 100644 index 0d3f8aed83d..00000000000 --- a/debian/mysql-common.postrm +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -e - -if [ "$1" = "purge" ]; then - rmdir /etc/mysql 2>/dev/null || true -fi - -#DEBHELPER# diff --git a/debian/po/POTFILES.in b/debian/po/POTFILES.in index 40b6d906195..804bf154b9b 100644 --- a/debian/po/POTFILES.in +++ b/debian/po/POTFILES.in @@ -1 +1 @@ -[type: gettext/rfc822deb] mariadb-server-10.0.templates +[type: gettext/rfc822deb] mariadb-galera-server-10.0.templates diff --git a/debian/po/ar.po b/debian/po/ar.po index 1507fcc92ab..aeb18dcc9fd 100644 --- a/debian/po/ar.po +++ b/debian/po/ar.po @@ -27,19 +27,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "Really proceed with downgrade?" msgstr "هل Ùعلاً تريد التثبيط؟" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "هناك مل٠مسمى /var/lib/mysql/debian-*.flag موجود على هذا النظام." #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 #, fuzzy #| msgid "" #| "Such file is an indication that a mariadb-server package with a higher " @@ -52,7 +52,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -62,13 +62,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "Important note for NIS/YP users" msgstr "ملاØظة هامة لمستخدمي NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -76,7 +76,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -88,13 +88,13 @@ msgstr "عليك أيضاً أن تقوم بالتأكد من صلاØيات Ù…Ø #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "إزالة جميع قواعد بيانات MariaDBØŸ" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -102,7 +102,7 @@ msgstr "الدليل /var/lib/mysql الذي ÙŠØتوي قواعد بيانات #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -113,13 +113,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "تشغيل خادم MariaDB عند الإقلاع؟" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -129,13 +129,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "كلمة المرور الجديدة لمستخد \"root\" الخاص بـMariaDB:" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -145,7 +145,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -153,7 +153,7 @@ msgstr "إن ترك الØقل Ùارغاً، Ùلن يتم تغيير كلمة #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 #, fuzzy #| msgid "New password for the MariaDB \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -161,13 +161,13 @@ msgstr "كلمة المرور الجديدة لمستخد \"root\" الخاص ب #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "تعذر تعيين كلمة مرور للمستخدم \"root\" الخاص بـMariaDB." #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -179,7 +179,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "You should check the account's password after tha package installation." @@ -188,7 +188,7 @@ msgstr "يجب عليك التØقق من كلمة مرور الØساب عقب #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " @@ -202,25 +202,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/ca.po b/debian/po/ca.po index 7ca3129f3c5..8814257569f 100644 --- a/debian/po/ca.po +++ b/debian/po/ca.po @@ -17,19 +17,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "Really proceed with downgrade?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "Such a file is an indication that a mariadb-server package with a higher " "version has been installed previously." @@ -37,7 +37,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -45,7 +45,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 #, fuzzy #| msgid "Important note for NIS/YP users!" msgid "Important note for NIS/YP users" @@ -53,7 +53,7 @@ msgstr "Nota important pels usuaris de NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -61,7 +61,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -69,13 +69,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -83,7 +83,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -92,7 +92,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 #, fuzzy #| msgid "Should MySQL start on boot?" msgid "Start the MariaDB server on boot?" @@ -100,7 +100,7 @@ msgstr "Voleu que el MariaDB s'iniciï a l'arrencada ?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 #, fuzzy msgid "" "The MariaDB server can be launched automatically at boot time or manually " @@ -112,13 +112,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -126,25 +126,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -153,13 +153,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "Please read the /usr/share/doc/mariadb-server-10.0/README.Debian file for " "more information." @@ -167,25 +167,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/cs.po b/debian/po/cs.po index 453bf5fb7fa..c1ce4ccc17e 100644 --- a/debian/po/cs.po +++ b/debian/po/cs.po @@ -26,19 +26,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "Really proceed with downgrade?" msgstr "Opravdu pokraÄovat v degradaci?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "V systému existuje soubor /var/lib/mysql/debian-*.flag." #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 #, fuzzy #| msgid "" #| "Such file is an indication that a mariadb-server package with a higher " @@ -51,7 +51,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -61,13 +61,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "Important note for NIS/YP users" msgstr "Důležitá poznámka pro uživatele NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -75,7 +75,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -88,13 +88,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Odstranit vÅ¡echny MariaDB databáze?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -104,7 +104,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -116,13 +116,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "Spustit MariaDB server pÅ™i startu systému?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -132,13 +132,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nové heslo MariaDB uživatele \"root\":" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -148,7 +148,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -156,7 +156,7 @@ msgstr "Ponecháte-li pole prázdné, heslo se nezmÄ›nÃ." #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 #, fuzzy #| msgid "New password for the MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -164,13 +164,13 @@ msgstr "Nové heslo MariaDB uživatele \"root\":" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Nelze nastavit heslo MariaDB uživatele \"root\"" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -182,7 +182,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "You should check the account's password after tha package installation." @@ -191,7 +191,7 @@ msgstr "Po instalaci balÃku byste mÄ›li heslo ověřit." #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " @@ -204,25 +204,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/da.po b/debian/po/da.po index e6836118840..bcc50345cd3 100644 --- a/debian/po/da.po +++ b/debian/po/da.po @@ -27,20 +27,20 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "Really proceed with downgrade?" msgstr "Ønsker du virkelig at fortsætte nedgraderingen?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" "Der er en fil med navnet /var/lib/mysql/debian-*.flag på dette system." #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 #, fuzzy #| msgid "" #| "Such file is an indication that a mariadb-server package with a higher " @@ -54,7 +54,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -64,13 +64,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "Important note for NIS/YP users" msgstr "Vigtig oplysning til NIS/YP-brugere" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -78,7 +78,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -91,13 +91,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Fjern alle MariaDB-databaser?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -107,7 +107,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -119,13 +119,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "Start MariaDB-serveren under systemopstart?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -135,13 +135,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Ny adgangskode for MariaDB's \"root\"-bruger:" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -151,7 +151,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -159,7 +159,7 @@ msgstr "Hvis du lader dette felt stå tomt, vil adgangskoden ikke blive ændret." #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 #, fuzzy #| msgid "New password for the MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -167,13 +167,13 @@ msgstr "Ny adgangskode for MariaDB's \"root\"-bruger:" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Kunne ikke sætte adgangskoden for MariaDB's \"root\"-bruger" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -186,13 +186,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "You should check the account's password after the package installation." msgstr "Du bør tjekke kontoens adgangskode efter pakkeinstallationen." #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " @@ -206,25 +206,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/de.po b/debian/po/de.po index 3a36bf7221f..f8d4dc7a895 100644 --- a/debian/po/de.po +++ b/debian/po/de.po @@ -29,13 +29,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "Really proceed with downgrade?" msgstr "Möchten Sie wirklich eine ältere Version einspielen?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" "Auf diesem System existiert eine Datei mit dem Namen /var/lib/mysql/debian-*." @@ -43,7 +43,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "Such a file is an indication that a mariadb-server package with a higher " "version has been installed previously." @@ -53,7 +53,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -63,13 +63,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "Important note for NIS/YP users" msgstr "Wichtige Anmerkung für NIS/YP-Benutzer!" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -79,7 +79,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -89,13 +89,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Alle MariaDB-Datenbanken entfernen?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -105,7 +105,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -117,13 +117,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "Soll der MariaDB-Server automatisch beim Booten starten?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -133,13 +133,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Neues Passwort für den MariaDB »root«-Benutzer:" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -149,25 +149,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "Wenn dieses Feld freigelassen wird, wird das Passwort nicht geändert." #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "Wiederholen Sie das Passwort für den MariaDB-»root«-Benutzer:" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Konnte für den MariaDB-»root«-Benutzer kein Passwort setzen" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -180,7 +180,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" "Sie sollten das Passwort des administrativen Benutzers nach der " @@ -188,7 +188,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mariadb-server-5.1/README.Debian file for " @@ -202,13 +202,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "Passwort-Eingabefehler" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" "Die beiden von Ihnen eingegebenen Passwörter sind nicht identisch. Bitte " @@ -216,13 +216,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "NDB-Cluster scheint gerade benutzt zu werden" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/es.po b/debian/po/es.po index f4e729b5f90..e88bcf1aa87 100644 --- a/debian/po/es.po +++ b/debian/po/es.po @@ -52,20 +52,20 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "Really proceed with downgrade?" msgstr "¿Desea realmente continuar con la desactualización?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" "Existe un archivo con el nombre /var/lib/mysql/debian-*.flag en este sistema." #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 #, fuzzy #| msgid "" #| "Such file is an indication that a mariadb-server package with a higher " @@ -79,7 +79,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -89,13 +89,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "Important note for NIS/YP users" msgstr "Nota importante para los usuarios de NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -103,7 +103,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -117,13 +117,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "¿Desea eliminar todas las bases de datos MariaDB?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -133,7 +133,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -145,13 +145,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "¿DeberÃa ejecutarse el servidor MariaDB al iniciarse el sistema?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -161,13 +161,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nueva contraseña para el usuario «root» de MariaDB:" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -177,7 +177,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -185,7 +185,7 @@ msgstr "No se modificará la contraseña si deja el espacio en blanco." #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 #, fuzzy #| msgid "New password for the MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -193,13 +193,13 @@ msgstr "Nueva contraseña para el usuario «root» de MariaDB:" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "No se pudo fijar la contraseña para el usuario «root» de MariaDB" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -212,7 +212,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" "DeberÃa comprobar la contraseña de la cuenta después de la instalación del " @@ -220,7 +220,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " @@ -234,25 +234,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/eu.po b/debian/po/eu.po index e5643f1ce65..a62bf4c3d5c 100644 --- a/debian/po/eu.po +++ b/debian/po/eu.po @@ -20,19 +20,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "Really proceed with downgrade?" msgstr "Benetan bertsio zaharragora itzuli nahi duzu?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "Sisteman badago /var/lib/mysql/debian-*.flag izeneko fitxategi bat." #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 #, fuzzy #| msgid "" #| "Such file is an indication that a mariadb-server package with a higher " @@ -46,7 +46,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -56,13 +56,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "Important note for NIS/YP users" msgstr "NIS/YP erabiltzaileentzat ohar garrantzitsua" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -70,7 +70,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -84,13 +84,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Ezabatu MariaDB datubase guztiak?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -99,7 +99,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -111,13 +111,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "Abioan MariaDB zerbitzaria abiarazi?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -127,13 +127,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "MariaDB \"root\" erabiltzailearen pasahitz berria:" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -143,7 +143,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -151,19 +151,19 @@ msgstr "Eremua hau zurian utziaz gero ez da pasahitza aldatuko." #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "Errepikatu MariaDB \"root\" erabiltzailearen pasahitza:" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Ezin da MariaDB \"root\" erabiltzailearen pasahitza ezarri" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -175,14 +175,14 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" "Kontuaren pasahitza egiaztatu beharko zenuke paketea instalatu aurretik." #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mariadb-server-10.0/README.Debian file for " @@ -196,25 +196,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "Pasahitz sarrera errorea" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "Idatzi dituzun bi pasahitzak ez dira berdina. Mesedez saiatu berriz." #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "Dirudienez NDB Cluster-a erabilia dago" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 #, fuzzy #| msgid "" #| "MySQL-5.1 has orphaned NDB Cluster support. Please migrate to the new " diff --git a/debian/po/fr.po b/debian/po/fr.po index da74e64a193..f2f87a915dd 100644 --- a/debian/po/fr.po +++ b/debian/po/fr.po @@ -22,19 +22,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "Really proceed with downgrade?" msgstr "Faut-il vraiment revenir à la version précédente ?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "Un fichier /var/lib/mysql/debian-*.flag est présent sur ce système." #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "Such a file is an indication that a mariadb-server package with a higher " "version has been installed previously." @@ -44,7 +44,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -52,13 +52,13 @@ msgstr "Il n'est pas garanti que cette version puisse en utiliser les données." #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "Important note for NIS/YP users" msgstr "Note importante pour les utilisateurs NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -68,7 +68,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -78,13 +78,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Faut-il supprimer toutes les bases de données MariaDB ?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -94,7 +94,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -105,13 +105,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "Faut-il lancer MariaDB au démarrage ?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -121,13 +121,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nouveau mot de passe du superutilisateur de MariaDB :" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -137,26 +137,26 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "Si ce champ est laissé vide, le mot de passe ne sera pas changé." #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "Confirmation du mot de passe du superutilisateur de MariaDB :" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "" "Impossible de changer le mot de passe de l'utilisateur « root » de MariaDB" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -168,7 +168,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" "Vous devriez vérifier le mot de passe de ce compte après l'installation du " @@ -176,7 +176,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mariadb-server-10.0/README.Debian file for " @@ -190,13 +190,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "Erreur de saisie du mot de passe" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" "Le mot de passe et sa confirmation ne sont pas identiques. Veuillez " @@ -204,13 +204,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "Abandon de la gestion de NDB" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/gl.po b/debian/po/gl.po index 30e58547e78..c3d399a3642 100644 --- a/debian/po/gl.po +++ b/debian/po/gl.po @@ -17,19 +17,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "Really proceed with downgrade?" msgstr "¿Quere pasar a unha versión anterior?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "Neste sistema hai un ficheiro chamado /var/lib/mysql/debian-*.flag." #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 #, fuzzy #| msgid "" #| "Such file is an indication that a mariadb-server package with a higher " @@ -43,7 +43,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -53,13 +53,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "Important note for NIS/YP users" msgstr "Nota importante para os usuarios de NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -67,7 +67,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -81,13 +81,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "¿Eliminar tódalas bases de datos de MariaDB?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -97,7 +97,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -109,13 +109,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "¿Iniciar o servidor MariaDB co ordenador?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -125,13 +125,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Novo contrasinal para o usuario \"root\" de MariaDB:" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -141,7 +141,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -149,7 +149,7 @@ msgstr "Se deixa o campo en branco, non se ha cambiar o contrasinal." #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 #, fuzzy #| msgid "New password for the MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -157,13 +157,13 @@ msgstr "Novo contrasinal para o usuario \"root\" de MariaDB:" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Non se puido establecer o contrasinal do usuario \"root\" de MariaDB" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -175,7 +175,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "You should check the account's password after tha package installation." @@ -184,7 +184,7 @@ msgstr "DeberÃa comprobar o contrasinal da conta trala instalación do paquete. #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " @@ -198,25 +198,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/it.po b/debian/po/it.po index b989f84fbf2..ec6751b2574 100644 --- a/debian/po/it.po +++ b/debian/po/it.po @@ -18,20 +18,20 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "Really proceed with downgrade?" msgstr "Procedere realmente con l'abbassamento di versione?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" "Su questo sistema esiste un file con nome /var/lib/mysql/debian-*.flag." #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "Such a file is an indication that a mariadb-server package with a higher " "version has been installed previously." @@ -41,7 +41,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -51,13 +51,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "Important note for NIS/YP users" msgstr "Nota importante per gli utenti NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -67,7 +67,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -77,13 +77,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Eliminare tutti i database MariaDB?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -93,7 +93,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -105,13 +105,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "Lanciare il server MariaDB all'avvio?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -121,13 +121,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nuova password per l'utente «root» di MariaDB:" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -137,25 +137,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "Se questo campo è lasciato vuoto, la password non viene cambiata." #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "Ripetere la password per l'utente «root» di MariaDB:" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Impossibile impostare la password per l'utente «root» di MariaDB" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -168,14 +168,14 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" "Al termine dell'installazione si deve verificare la password dell'account." #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mariadb-server-10.0/README.Debian file for " @@ -189,25 +189,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "Errore di inserimento della password" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "Le due password inserite sono diverse. Riprovare." #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "È in uso un cluster NDB" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/ja.po b/debian/po/ja.po index 4cc190425f4..692c2e3686c 100644 --- a/debian/po/ja.po +++ b/debian/po/ja.po @@ -27,13 +27,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "Really proceed with downgrade?" msgstr "本当ã«ãƒ€ã‚¦ãƒ³ã‚°ãƒ¬ãƒ¼ãƒ‰ã‚’実行ã—ã¾ã™ã‹?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" "ã“ã®ã‚·ã‚¹ãƒ†ãƒ ã«ã¯ /var/lib/mysql/debian-*.flag ã¨ã„ã†åå‰ã®ãƒ•ã‚¡ã‚¤ãƒ«ãŒå˜åœ¨ã—ã¦" @@ -41,7 +41,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "Such a file is an indication that a mariadb-server package with a higher " "version has been installed previously." @@ -51,7 +51,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -61,13 +61,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "Important note for NIS/YP users" msgstr "NIS/YP ユーザã¸ã®é‡è¦ãªæ³¨æ„" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -77,7 +77,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -85,13 +85,13 @@ msgstr "/var/lib/mysql ã®æ‰€æœ‰è€…権é™ã‚’ãƒã‚§ãƒƒã‚¯ã™ã‚‹å¿…è¦ã‚‚ã‚ã‚Šã¾ #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "ã™ã¹ã¦ã® MariaDB データベースを削除ã—ã¾ã™ã‹?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -101,7 +101,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -113,13 +113,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "MariaDB をシステム起動時ã«é–‹å§‹ã—ã¾ã™ã‹?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -129,13 +129,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "MariaDB ã® \"root\" ユーザã«å¯¾ã™ã‚‹æ–°ã—ã„パスワード:" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -145,25 +145,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "ã“ã®å€¤ã‚’空ã®ã¾ã¾ã«ã—ã¦ãŠã„ãŸå ´åˆã¯ã€ãƒ‘スワードã¯å¤‰æ›´ã•ã‚Œã¾ã›ã‚“。" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "MariaDB ã® \"root\" ユーザã«å¯¾ã™ã‚‹æ–°ã—ã„パスワード:" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "MariaDB ã® \"root\" ユーザã®ãƒ‘スワードをè¨å®šã§ãã¾ã›ã‚“" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -175,14 +175,14 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" "パッケージã®ã‚¤ãƒ³ã‚¹ãƒˆãƒ¼ãƒ«å¾Œã€ã‚¢ã‚«ã‚¦ãƒ³ãƒˆã®ãƒ‘スワードを確èªã™ã‚‹å¿…è¦ãŒã‚ã‚Šã¾ã™ã€‚" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mariadb-server-10.0/README.Debian file for " @@ -195,25 +195,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "パスワード入力エラー" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "入力ã•ã‚ŒãŸäºŒã¤ã®ãƒ‘スワードãŒä¸€è‡´ã—ã¾ã›ã‚“。å†å…¥åŠ›ã—ã¦ãã ã•ã„。" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "NDB クラスタãŒåˆ©ç”¨ã•ã‚Œã¦ã„るよã†ã§ã™" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/nb.po b/debian/po/nb.po index ed02ca1d48e..e8509bea43b 100644 --- a/debian/po/nb.po +++ b/debian/po/nb.po @@ -19,7 +19,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 #, fuzzy #| msgid "Do you really want to downgrade?" msgid "Really proceed with downgrade?" @@ -27,13 +27,13 @@ msgstr "Er du sikker pÃ¥ at du vil nedgradere?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 #, fuzzy #| msgid "" #| "WARNING: The file /var/lib/mysql/debian-*.flag exists. This indicates " @@ -50,7 +50,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -58,7 +58,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 #, fuzzy #| msgid "Important note for NIS/YP users!" msgid "Important note for NIS/YP users" @@ -66,7 +66,7 @@ msgstr "Viktig merknad for NIS/YP-brukere!" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -74,7 +74,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -82,13 +82,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -96,7 +96,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 #, fuzzy #| msgid "" #| "The script is about to remove the data directory /var/lib/mysql. If it is " @@ -113,7 +113,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 #, fuzzy #| msgid "Should MySQL start on boot?" msgid "Start the MariaDB server on boot?" @@ -121,7 +121,7 @@ msgstr "Skal MariaDB startes ved maskinoppstart?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 #, fuzzy #| msgid "" #| "The MySQL can start automatically on boot time or only if you manually " @@ -135,7 +135,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 #, fuzzy #| msgid "New password for MySQL \"root\" user:" msgid "New password for the MariaDB \"root\" user:" @@ -143,7 +143,7 @@ msgstr "Nytt passord for MariaDBs «root»-bruker:" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 #, fuzzy #| msgid "" #| "It is highly recommended that you set a password for the MySQL " @@ -157,13 +157,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 #, fuzzy #| msgid "New password for MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -171,7 +171,7 @@ msgstr "Nytt passord for MariaDBs «root»-bruker:" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "Unable to set password for MySQL \"root\" user" msgid "Unable to set password for the MariaDB \"root\" user" @@ -179,7 +179,7 @@ msgstr "Klarer ikke angi passord for MariaDBs «root»-bruker" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "It seems an error occurred while setting the password for the MySQL " @@ -198,13 +198,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "Please read the /usr/share/doc/mariadb-server-10.0/README.Debian file for " "more information." @@ -212,25 +212,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/nl.po b/debian/po/nl.po index a3694f6eea0..accf69555ef 100644 --- a/debian/po/nl.po +++ b/debian/po/nl.po @@ -18,7 +18,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 #, fuzzy #| msgid "Do you really want to downgrade?" msgid "Really proceed with downgrade?" @@ -26,13 +26,13 @@ msgstr "Wilt u echt een oude versie herstellen?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 #, fuzzy #| msgid "" #| "WARNING: The file /var/lib/mysql/debian-*.flag exists. This indicates " @@ -50,7 +50,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -58,7 +58,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 #, fuzzy #| msgid "Important note for NIS/YP users!" msgid "Important note for NIS/YP users" @@ -66,7 +66,7 @@ msgstr "Belangrijke opmerking voor gebruikers van NIS/YP!" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -74,7 +74,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -82,13 +82,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -96,7 +96,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 #, fuzzy #| msgid "" #| "The script is about to remove the data directory /var/lib/mysql. If it is " @@ -114,7 +114,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 #, fuzzy #| msgid "Should MySQL start on boot?" msgid "Start the MariaDB server on boot?" @@ -122,7 +122,7 @@ msgstr "Moet MariaDB starten als de computer start?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 #, fuzzy #| msgid "" #| "The MySQL can start automatically on boot time or only if you manually " @@ -136,7 +136,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 #, fuzzy #| msgid "New password for MySQL \"root\" user:" msgid "New password for the MariaDB \"root\" user:" @@ -144,7 +144,7 @@ msgstr "Nieuw wachtwoord voor de MariaDB \"root\"-gebruiker:" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 #, fuzzy #| msgid "" #| "It is highly recommended that you set a password for the MySQL " @@ -158,13 +158,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 #, fuzzy #| msgid "New password for MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -172,7 +172,7 @@ msgstr "Nieuw wachtwoord voor de MariaDB \"root\"-gebruiker:" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "Unable to set password for MySQL \"root\" user" msgid "Unable to set password for the MariaDB \"root\" user" @@ -180,7 +180,7 @@ msgstr "Kan het wachtwoord voor de MariaDB \"root\"-gebruiker niet instellen" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "It seems an error occurred while setting the password for the MySQL " @@ -199,13 +199,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "Please read the /usr/share/doc/mariadb-server-10.0/README.Debian file for " "more information." @@ -213,25 +213,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/pt.po b/debian/po/pt.po index 4f2e646dcc7..7be7dde415b 100644 --- a/debian/po/pt.po +++ b/debian/po/pt.po @@ -18,19 +18,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "Really proceed with downgrade?" msgstr "Deseja mesmo fazer downgrade?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "Existe um ficheiro chamado /var/lib/mysql/debian-*.flag neste sistema." #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 #, fuzzy #| msgid "" #| "Such file is an indication that a mariadb-server package with a higher " @@ -44,7 +44,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -54,13 +54,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "Important note for NIS/YP users" msgstr "Nota importante para utilizadores de NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -68,7 +68,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -81,13 +81,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Remover todas as bases de dados MariaDB?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -97,7 +97,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -109,13 +109,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "Iniciar o servidor MariaDB no arranque?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -125,13 +125,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nova palavra-passe para o utilizador \"root\" do MariaDB:" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -141,7 +141,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -150,7 +150,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 #, fuzzy #| msgid "New password for the MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -158,7 +158,7 @@ msgstr "Nova palavra-passe para o utilizador \"root\" do MariaDB:" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "" "Não foi possÃvel definir a palavra-passe para o utilizador \"root\" do " @@ -166,7 +166,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -179,7 +179,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "You should check the account's password after tha package installation." @@ -189,7 +189,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " @@ -203,25 +203,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/pt_BR.po b/debian/po/pt_BR.po index 7cfa5a05190..dd8fb9c1f15 100644 --- a/debian/po/pt_BR.po +++ b/debian/po/pt_BR.po @@ -21,19 +21,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "Really proceed with downgrade?" msgstr "Realmente proceder com o rebaixamento de versão?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "Um arquivo de nome /var/lib/mysql/debian-*.flag existe no sistema." #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 #, fuzzy #| msgid "" #| "Such file is an indication that a mariadb-server package with a higher " @@ -47,7 +47,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -57,13 +57,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "Important note for NIS/YP users" msgstr "Aviso importante para usuários NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -71,7 +71,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 #, fuzzy #| msgid "" #| "You should also check the permissions and the owner of the /var/lib/mysql " @@ -84,13 +84,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Remover todas as bases de dados do MariaDB?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -100,7 +100,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -112,13 +112,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "Iniciar o servidor MariaDB junto a inicialização da máquina?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -128,13 +128,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nova senha para o usuário \"root\" do MariaDB:" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -144,7 +144,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 #, fuzzy #| msgid "If that field is left blank, the password will not be changed." msgid "If this field is left blank, the password will not be changed." @@ -152,7 +152,7 @@ msgstr "Caso este campo seja deixado em branco, a senha não sera mudada." #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 #, fuzzy #| msgid "New password for the MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -160,13 +160,13 @@ msgstr "Nova senha para o usuário \"root\" do MariaDB:" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "ImpossÃvel definir senha para o usuário \"root\" do MariaDB" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -179,7 +179,7 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "You should check the account's password after tha package installation." @@ -188,7 +188,7 @@ msgstr "Você deverá checar a senha dessa conta após a instalação deste paco #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mysql-server-5.1/README.Debian file for " @@ -202,25 +202,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/ro.po b/debian/po/ro.po index a0c69e7161f..ec71d628021 100644 --- a/debian/po/ro.po +++ b/debian/po/ro.po @@ -19,7 +19,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 #, fuzzy #| msgid "Do you really want to downgrade?" msgid "Really proceed with downgrade?" @@ -27,13 +27,13 @@ msgstr "SunteÅ£i sigur că doriÅ£i să instalaÅ£i o versiune mai veche?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 #, fuzzy #| msgid "" #| "WARNING: The file /var/lib/mysql/debian-*.flag exists. This indicates " @@ -50,7 +50,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -58,7 +58,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 #, fuzzy #| msgid "Important note for NIS/YP users!" msgid "Important note for NIS/YP users" @@ -66,7 +66,7 @@ msgstr "Notă importantă pentru utilizatorii NIS/YP!" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -74,7 +74,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -82,13 +82,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -96,7 +96,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 #, fuzzy #| msgid "" #| "The script is about to remove the data directory /var/lib/mysql. If it is " @@ -113,7 +113,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 #, fuzzy #| msgid "Should MySQL start on boot?" msgid "Start the MariaDB server on boot?" @@ -121,7 +121,7 @@ msgstr "DoriÅ£i ca MariaDB să pornească la initializarea sistemului?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 #, fuzzy #| msgid "" #| "The MySQL can start automatically on boot time or only if you manually " @@ -135,7 +135,7 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 #, fuzzy #| msgid "New password for MySQL \"root\" user:" msgid "New password for the MariaDB \"root\" user:" @@ -143,7 +143,7 @@ msgstr "Noua parolă pentru utilizatorul „root†al MariaDB:" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 #, fuzzy #| msgid "" #| "It is highly recommended that you set a password for the MySQL " @@ -157,13 +157,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 #, fuzzy #| msgid "New password for MySQL \"root\" user:" msgid "Repeat password for the MariaDB \"root\" user:" @@ -171,7 +171,7 @@ msgstr "Noua parolă pentru utilizatorul „root†al MariaDB:" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "Unable to set password for MySQL \"root\" user" msgid "Unable to set password for the MariaDB \"root\" user" @@ -179,7 +179,7 @@ msgstr "Nu s-a putut stabili parola pentru utilizatorul „root†al MariaDB" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "It seems an error occurred while setting the password for the MySQL " @@ -198,13 +198,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "Please read the /usr/share/doc/mariadb-server-10.0/README.Debian file for " "more information." @@ -212,25 +212,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/ru.po b/debian/po/ru.po index e1e73ee2748..d555c6b086d 100644 --- a/debian/po/ru.po +++ b/debian/po/ru.po @@ -32,19 +32,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "Really proceed with downgrade?" msgstr "ДейÑтвительно уÑтановить более Ñтарую верÑию?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "Ð’ ÑиÑтеме найден файл /var/lib/mysql/debian-*.flag." #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "Such a file is an indication that a mariadb-server package with a higher " "version has been installed previously." @@ -54,7 +54,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -64,13 +64,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "Important note for NIS/YP users" msgstr "Важное замечание Ð´Ð»Ñ Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»ÐµÐ¹ NIS/YP" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -80,7 +80,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -88,13 +88,13 @@ msgstr "Также проверьте права доÑтупа и Ð²Ð»Ð°Ð´ÐµÐ»Ñ #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Удалить вÑе базы данных MariaDB?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -103,7 +103,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -115,13 +115,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "ЗапуÑкать MariaDB при загрузке ÑиÑтемы?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -131,13 +131,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Ðовый пароль Ð´Ð»Ñ MariaDB Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ \"root\":" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -147,25 +147,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "ЕÑли оÑтавить поле пуÑтым, то пароль изменён не будет." #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "Повторите ввод Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð´Ð»Ñ MariaDB Ð¿Ð¾Ð»ÑŒÐ·Ð¾Ð²Ð°Ñ‚ÐµÐ»Ñ \"root\":" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Ðевозможно задать пароль MariaDB пользователю \"root\"" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -177,13 +177,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "You should check the account's password after the package installation." msgstr "Проверьте пароль учётной запиÑи поÑле уÑтановки пакета." #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mariadb-server-10.0/README.Debian file for " @@ -196,25 +196,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "Ошибка ввода паролÑ" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "Два введённых Ð¿Ð°Ñ€Ð¾Ð»Ñ Ð½Ðµ одинаковы. Повторите ввод." #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "NDB Cluster уже иÑпользуетÑÑ" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/sv.po b/debian/po/sv.po index 2aec886a6dd..586dd7f460f 100644 --- a/debian/po/sv.po +++ b/debian/po/sv.po @@ -21,19 +21,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "Really proceed with downgrade?" msgstr "Vill du verkligen genomföra nedgraderingen?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "En fil med namnet /var/lib/mysql/debian-*.flag hittades i systemet." #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "Such a file is an indication that a mariadb-server package with a higher " "version has been installed previously." @@ -43,7 +43,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -53,13 +53,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "Important note for NIS/YP users" msgstr "Viktig information för NIS/YP-användare" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -69,7 +69,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -79,13 +79,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "Ta bort alla MariaDB-databaser?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -95,7 +95,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -107,13 +107,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "Ska MariaDB startas vid systemets uppstart?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -123,13 +123,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "Nytt lösenord för MariaDBs \"root\"-användare:" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -139,25 +139,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "Om detta fält lämnas tom kommer lösenordet inte att ändras." #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "Repetera lösenordet för MariaDBs \"root\"-användare:" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "Kunde inte sätta lösenord för MariaDBs \"root\"-användare" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -170,13 +170,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "You should check the account's password after the package installation." msgstr "Du bör kontrollera kontots lösenord efter installationen av paketet." #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 #, fuzzy #| msgid "" #| "Please read the /usr/share/doc/mariadb-server-10.0/README.Debian file for " @@ -190,25 +190,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "Fel vid inmatning av lösenord" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "De tvÃ¥ lösenorden du angav stämde inte överrens. Prova igen." #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "NDB-kluster används inte" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/templates.pot b/debian/po/templates.pot index b046b068ff9..c67429d7706 100644 --- a/debian/po/templates.pot +++ b/debian/po/templates.pot @@ -19,19 +19,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "Really proceed with downgrade?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "Such a file is an indication that a mariadb-server package with a higher " "version has been installed previously." @@ -39,7 +39,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -47,13 +47,13 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "Important note for NIS/YP users" msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -61,7 +61,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -69,13 +69,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -83,7 +83,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -92,13 +92,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "Start the MariaDB server on boot?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 msgid "" "The MariaDB server can be launched automatically at boot time or manually " "with the '/etc/init.d/mysql start' command." @@ -106,13 +106,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -120,25 +120,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -147,13 +147,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "Please read the /usr/share/doc/mariadb-server-10.0/README.Debian file for " "more information." @@ -161,25 +161,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/debian/po/tr.po b/debian/po/tr.po index a648bf38698..789ff9f8e2b 100644 --- a/debian/po/tr.po +++ b/debian/po/tr.po @@ -18,19 +18,19 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "Really proceed with downgrade?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "A file named /var/lib/mysql/debian-*.flag exists on this system." msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "Such a file is an indication that a mariadb-server package with a higher " "version has been installed previously." @@ -38,7 +38,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:2001 +#: ../mariadb-galera-server-10.0.templates:2001 msgid "" "There is no guarantee that the version you're currently installing will be " "able to use the current databases." @@ -46,7 +46,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 #, fuzzy #| msgid "Important note for NIS/YP users!" msgid "Important note for NIS/YP users" @@ -54,7 +54,7 @@ msgstr "NIS/YP kullanıcıları için önemli not!" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "Using MariaDB under NIS/YP requires a mysql user account to be added on the " "local system with:" @@ -62,7 +62,7 @@ msgstr "" #. Type: note #. Description -#: ../mariadb-server-10.0.templates:3001 +#: ../mariadb-galera-server-10.0.templates:3001 msgid "" "You should also check the permissions and ownership of the /var/lib/mysql " "directory:" @@ -70,13 +70,13 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "Remove all MariaDB databases?" msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "The /var/lib/mysql directory which contains the MariaDB databases is about " "to be removed." @@ -84,7 +84,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:4001 +#: ../mariadb-galera-server-10.0.templates:4001 msgid "" "If you're removing the MariaDB package in order to later install a more " "recent version or if a different mariadb-server package is already using it, " @@ -93,7 +93,7 @@ msgstr "" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 #, fuzzy #| msgid "Should MySQL start on boot?" msgid "Start the MariaDB server on boot?" @@ -101,7 +101,7 @@ msgstr "MariaDB açılış sırasında baÅŸlatılsın mı?" #. Type: boolean #. Description -#: ../mariadb-server-10.0.templates:5001 +#: ../mariadb-galera-server-10.0.templates:5001 #, fuzzy msgid "" "The MariaDB server can be launched automatically at boot time or manually " @@ -113,13 +113,13 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "New password for the MariaDB \"root\" user:" msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "" "While not mandatory, it is highly recommended that you set a password for " "the MariaDB administrative \"root\" user." @@ -127,25 +127,25 @@ msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:6001 +#: ../mariadb-galera-server-10.0.templates:6001 msgid "If this field is left blank, the password will not be changed." msgstr "" #. Type: password #. Description -#: ../mariadb-server-10.0.templates:7001 +#: ../mariadb-galera-server-10.0.templates:7001 msgid "Repeat password for the MariaDB \"root\" user:" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "Unable to set password for the MariaDB \"root\" user" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "An error occurred while setting the password for the MariaDB administrative " "user. This may have happened because the account already has a password, or " @@ -154,13 +154,13 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "You should check the account's password after the package installation." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:8001 +#: ../mariadb-galera-server-10.0.templates:8001 msgid "" "Please read the /usr/share/doc/mariadb-server-10.0/README.Debian file for " "more information." @@ -168,25 +168,25 @@ msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "Password input error" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:9001 +#: ../mariadb-galera-server-10.0.templates:9001 msgid "The two passwords you entered were not the same. Please try again." msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "NDB Cluster seems to be in use" msgstr "" #. Type: error #. Description -#: ../mariadb-server-10.0.templates:10001 +#: ../mariadb-galera-server-10.0.templates:10001 msgid "" "MySQL-5.1 no longer provides NDB Cluster support. Please migrate to the new " "mysql-cluster package and remove all lines starting with \"ndb\" from all " diff --git a/include/thr_lock.h b/include/thr_lock.h index 3f7a5ca988f..4551a3160ff 100644 --- a/include/thr_lock.h +++ b/include/thr_lock.h @@ -20,6 +20,15 @@ #ifdef __cplusplus extern "C" { #endif +#ifdef WITH_WSREP +#include <my_sys.h> + typedef int (* wsrep_thd_is_brute_force_fun)(void *); + typedef int (* wsrep_abort_thd_fun)(void *, void *, my_bool); + typedef int (* wsrep_on_fun)(void *); + void wsrep_thr_lock_init( + wsrep_thd_is_brute_force_fun bf_fun, wsrep_abort_thd_fun abort_fun, + my_bool debug, my_bool convert_LOCK_to_trx, wsrep_on_fun on_fun); +#endif #include <my_pthread.h> #include <my_list.h> @@ -95,6 +104,10 @@ typedef struct st_thr_lock_info { pthread_t thread; my_thread_id thread_id; +#ifdef WITH_WSREP + void *mysql_thd; // THD pointer + my_bool in_lock_tables; // true, if inside locking session +#endif } THR_LOCK_INFO; diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index ce962a96f29..cf62412fa2f 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1573,50 +1573,10 @@ id select_type table type possible_keys key key_len ref rows Extra explain select count(*) from information_schema.views; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE views ALL NULL NULL NULL NULL NULL Open_frm_only; Scanned all databases -set global init_connect="drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;"; -select * from information_schema.global_variables where variable_name='init_connect'; -VARIABLE_NAME VARIABLE_VALUE -INIT_CONNECT drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists t1; -drop table if exists t1;drop table if exists +set global init_connect=repeat("drop table if exists t1;", 100); +select length(@@global.init_connect), length(variable_value) from information_schema.global_variables where variable_name='init_connect'; +length(@@global.init_connect) length(variable_value) +2400 2048 Warnings: Warning 1265 Data truncated for column 'VARIABLE_VALUE' at row 1 set global init_connect=""; diff --git a/mysql-test/r/mysqld--help.result b/mysql-test/r/mysqld--help.result index 51dfc3123a4..3a2e1ab35f1 100644 --- a/mysql-test/r/mysqld--help.result +++ b/mysql-test/r/mysqld--help.result @@ -983,6 +983,75 @@ The following options may be given as the first argument: -V, --version Output version information and exit. --wait-timeout=# The number of seconds the server waits for activity on a connection before closing it + --wsrep-OSU-method[=name] + Method for Online Schema Upgrade + --wsrep-auto-increment-control + To automatically control the assignment of autoincrement + variables + (Defaults to on; use --skip-wsrep-auto-increment-control to disable.) + --wsrep-causal-reads + Enable "strictly synchronous" semantics for read + operations + --wsrep-certify-nonPK + Certify tables with no primary key + (Defaults to on; use --skip-wsrep-certify-nonPK to disable.) + --wsrep-cluster-address=name + Address to initially connect to cluster + --wsrep-cluster-name=name + Name for the cluster + --wsrep-convert-LOCK-to-trx + To convert locking sessions into transactions + --wsrep-data-home-dir=name + home directory for wsrep provider + --wsrep-dbug-option=name + DBUG options to provider library + --wsrep-debug To enable debug level logging + --wsrep-drupal-282555-workaround + To use a workaround forbad autoincrement value + --wsrep-forced-binlog-format=name + binlog format to take effect over user's choice + --wsrep-log-conflicts + To log multi-master conflicts + --wsrep-max-ws-rows=# + Max number of rows in write set + --wsrep-max-ws-size=# + Max write set size (bytes) + --wsrep-mysql-replication-bundle=# + mysql replication group commit + --wsrep-node-address=name + Node address + --wsrep-node-incoming-address=name + Client connection address + --wsrep-node-name=name + Node name + --wsrep-notify-cmd=name + --wsrep-on To enable wsrep replication + (Defaults to on; use --skip-wsrep-on to disable.) + --wsrep-provider=name + Path to replication provider library + --wsrep-provider-options=name + provider specific options + --wsrep-recover Recover database state after crash and exit + --wsrep-replicate-myisam + To enable myisam replication + --wsrep-retry-autocommit=# + Max number of times to retry a failed autocommit + statement + --wsrep-slave-threads=# + Number of slave appliers to launch + --wsrep-sst-auth=name + Authentication for SST connection + --wsrep-sst-donor=name + preferred donor node for the SST + --wsrep-sst-donor-rejects-queries + Reject client queries when donating state snapshot + transfer + --wsrep-sst-method=name + State snapshot transfer method + --wsrep-sst-receive-address=name + Address where node is waiting for SST contact + --wsrep-start-position=name + global transaction position to start from Variables (--variable-name=value) allow-suspicious-udfs FALSE @@ -1268,6 +1337,38 @@ use-stat-tables NEVER userstat FALSE verbose TRUE wait-timeout 28800 +wsrep-OSU-method TOI +wsrep-auto-increment-control TRUE +wsrep-causal-reads FALSE +wsrep-certify-nonPK TRUE +wsrep-cluster-address +wsrep-cluster-name my_wsrep_cluster +wsrep-convert-LOCK-to-trx FALSE +wsrep-data-home-dir +wsrep-dbug-option +wsrep-debug FALSE +wsrep-drupal-282555-workaround FALSE +wsrep-forced-binlog-format NONE +wsrep-log-conflicts FALSE +wsrep-max-ws-rows 131072 +wsrep-max-ws-size 1073741824 +wsrep-mysql-replication-bundle 0 +wsrep-node-address +wsrep-node-incoming-address AUTO +wsrep-notify-cmd +wsrep-on FALSE +wsrep-provider none +wsrep-provider-options +wsrep-recover FALSE +wsrep-replicate-myisam FALSE +wsrep-retry-autocommit 1 +wsrep-slave-threads 1 +wsrep-sst-auth (No default value) +wsrep-sst-donor +wsrep-sst-donor-rejects-queries FALSE +wsrep-sst-method mysqldump +wsrep-sst-receive-address AUTO +wsrep-start-position 00000000-0000-0000-0000-000000000000:-1 To see what values a running MySQL server is using, type 'mysqladmin variables' instead of 'mysqld --verbose --help'. diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 2b7439b09e0..567e878edda 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -101,19 +101,19 @@ drop table t1; show variables like "wait_timeout%"; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def information_schema VARIABLES VARIABLES VARIABLE_NAME Variable_name 253 64 12 N 1 0 8 -def information_schema VARIABLES VARIABLES VARIABLE_VALUE Value 253 1024 5 Y 0 0 8 +def information_schema VARIABLES VARIABLES VARIABLE_VALUE Value 253 2048 5 Y 0 0 8 Variable_name Value wait_timeout 28800 show variables like "WAIT_timeout%"; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def information_schema VARIABLES VARIABLES VARIABLE_NAME Variable_name 253 64 12 N 1 0 8 -def information_schema VARIABLES VARIABLES VARIABLE_VALUE Value 253 1024 5 Y 0 0 8 +def information_schema VARIABLES VARIABLES VARIABLE_VALUE Value 253 2048 5 Y 0 0 8 Variable_name Value wait_timeout 28800 show variables like "this_doesn't_exists%"; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr def information_schema VARIABLES VARIABLES VARIABLE_NAME Variable_name 253 64 0 N 1 0 8 -def information_schema VARIABLES VARIABLES VARIABLE_VALUE Value 253 1024 0 Y 0 0 8 +def information_schema VARIABLES VARIABLES VARIABLE_VALUE Value 253 2048 0 Y 0 0 8 Variable_name Value show table status from test like "this_doesn't_exists%"; Catalog Database Table Table_alias Column Column_alias Type Length Max length Is_null Flags Decimals Charsetnr diff --git a/mysql-test/suite/funcs_1/r/is_columns_is.result b/mysql-test/suite/funcs_1/r/is_columns_is.result index 8bf290ba168..75b87daa86c 100644 --- a/mysql-test/suite/funcs_1/r/is_columns_is.result +++ b/mysql-test/suite/funcs_1/r/is_columns_is.result @@ -147,9 +147,9 @@ def information_schema FILES UPDATE_COUNT 13 NULL YES bigint NULL NULL 19 0 NULL def information_schema FILES UPDATE_TIME 34 NULL YES datetime NULL NULL NULL NULL 0 NULL NULL datetime select def information_schema FILES VERSION 25 NULL YES bigint NULL NULL 20 0 NULL NULL NULL bigint(21) unsigned select def information_schema GLOBAL_STATUS VARIABLE_NAME 1 NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select -def information_schema GLOBAL_STATUS VARIABLE_VALUE 2 NULL YES varchar 1024 3072 NULL NULL NULL utf8 utf8_general_ci varchar(1024) select +def information_schema GLOBAL_STATUS VARIABLE_VALUE 2 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select def information_schema GLOBAL_VARIABLES VARIABLE_NAME 1 NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select -def information_schema GLOBAL_VARIABLES VARIABLE_VALUE 2 NULL YES varchar 1024 3072 NULL NULL NULL utf8 utf8_general_ci varchar(1024) select +def information_schema GLOBAL_VARIABLES VARIABLE_VALUE 2 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select def information_schema INDEX_STATISTICS INDEX_NAME 3 NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) select def information_schema INDEX_STATISTICS ROWS_READ 4 0 NO bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select def information_schema INDEX_STATISTICS TABLE_NAME 2 NO varchar 192 576 NULL NULL NULL utf8 utf8_general_ci varchar(192) select @@ -299,9 +299,9 @@ def information_schema SCHEMA_PRIVILEGES PRIVILEGE_TYPE 4 NO varchar 64 192 NUL def information_schema SCHEMA_PRIVILEGES TABLE_CATALOG 2 NO varchar 512 1536 NULL NULL NULL utf8 utf8_general_ci varchar(512) select def information_schema SCHEMA_PRIVILEGES TABLE_SCHEMA 3 NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select def information_schema SESSION_STATUS VARIABLE_NAME 1 NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select -def information_schema SESSION_STATUS VARIABLE_VALUE 2 NULL YES varchar 1024 3072 NULL NULL NULL utf8 utf8_general_ci varchar(1024) select +def information_schema SESSION_STATUS VARIABLE_VALUE 2 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select def information_schema SESSION_VARIABLES VARIABLE_NAME 1 NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select -def information_schema SESSION_VARIABLES VARIABLE_VALUE 2 NULL YES varchar 1024 3072 NULL NULL NULL utf8 utf8_general_ci varchar(1024) select +def information_schema SESSION_VARIABLES VARIABLE_VALUE 2 NULL YES varchar 2048 6144 NULL NULL NULL utf8 utf8_general_ci varchar(2048) select def information_schema STATISTICS CARDINALITY 10 NULL YES bigint NULL NULL 19 0 NULL NULL NULL bigint(21) select def information_schema STATISTICS COLLATION 9 NULL YES varchar 1 3 NULL NULL NULL utf8 utf8_general_ci varchar(1) select def information_schema STATISTICS COLUMN_NAME 8 NO varchar 64 192 NULL NULL NULL utf8 utf8_general_ci varchar(64) select @@ -630,9 +630,9 @@ NULL information_schema FILES CHECKSUM bigint NULL NULL NULL NULL bigint(21) uns 3.0000 information_schema FILES STATUS varchar 20 60 utf8 utf8_general_ci varchar(20) 3.0000 information_schema FILES EXTRA varchar 255 765 utf8 utf8_general_ci varchar(255) 3.0000 information_schema GLOBAL_STATUS VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) -3.0000 information_schema GLOBAL_STATUS VARIABLE_VALUE varchar 1024 3072 utf8 utf8_general_ci varchar(1024) +3.0000 information_schema GLOBAL_STATUS VARIABLE_VALUE varchar 2048 6144 utf8 utf8_general_ci varchar(2048) 3.0000 information_schema GLOBAL_VARIABLES VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) -3.0000 information_schema GLOBAL_VARIABLES VARIABLE_VALUE varchar 1024 3072 utf8 utf8_general_ci varchar(1024) +3.0000 information_schema GLOBAL_VARIABLES VARIABLE_VALUE varchar 2048 6144 utf8 utf8_general_ci varchar(2048) 3.0000 information_schema INDEX_STATISTICS TABLE_SCHEMA varchar 192 576 utf8 utf8_general_ci varchar(192) 3.0000 information_schema INDEX_STATISTICS TABLE_NAME varchar 192 576 utf8 utf8_general_ci varchar(192) 3.0000 information_schema INDEX_STATISTICS INDEX_NAME varchar 192 576 utf8 utf8_general_ci varchar(192) @@ -782,9 +782,9 @@ NULL information_schema ROUTINES LAST_ALTERED datetime NULL NULL NULL NULL datet 3.0000 information_schema SCHEMA_PRIVILEGES PRIVILEGE_TYPE varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema SCHEMA_PRIVILEGES IS_GRANTABLE varchar 3 9 utf8 utf8_general_ci varchar(3) 3.0000 information_schema SESSION_STATUS VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) -3.0000 information_schema SESSION_STATUS VARIABLE_VALUE varchar 1024 3072 utf8 utf8_general_ci varchar(1024) +3.0000 information_schema SESSION_STATUS VARIABLE_VALUE varchar 2048 6144 utf8 utf8_general_ci varchar(2048) 3.0000 information_schema SESSION_VARIABLES VARIABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) -3.0000 information_schema SESSION_VARIABLES VARIABLE_VALUE varchar 1024 3072 utf8 utf8_general_ci varchar(1024) +3.0000 information_schema SESSION_VARIABLES VARIABLE_VALUE varchar 2048 6144 utf8 utf8_general_ci varchar(2048) 3.0000 information_schema STATISTICS TABLE_CATALOG varchar 512 1536 utf8 utf8_general_ci varchar(512) 3.0000 information_schema STATISTICS TABLE_SCHEMA varchar 64 192 utf8 utf8_general_ci varchar(64) 3.0000 information_schema STATISTICS TABLE_NAME varchar 64 192 utf8 utf8_general_ci varchar(64) diff --git a/mysql-test/suite/innodb/r/innodb-autoinc.result b/mysql-test/suite/innodb/r/innodb-autoinc.result index c4504f6d348..778fb3ce913 100644 --- a/mysql-test/suite/innodb/r/innodb-autoinc.result +++ b/mysql-test/suite/innodb/r/innodb-autoinc.result @@ -201,6 +201,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 100 auto_increment_offset 10 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -234,6 +235,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -273,6 +275,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -286,6 +289,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 100 auto_increment_offset 10 +wsrep_auto_increment_control ON INSERT INTO t1 VALUES (-2), (NULL),(2),(NULL); INSERT INTO t1 VALUES (250),(NULL); SELECT * FROM t1; @@ -319,6 +323,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -334,6 +339,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 100 auto_increment_offset 10 +wsrep_auto_increment_control ON INSERT INTO t1 VALUES (-2); Warnings: Warning 1264 Out of range value for column 'c1' at row 1 @@ -374,6 +380,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -389,6 +396,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 100 auto_increment_offset 10 +wsrep_auto_increment_control ON INSERT INTO t1 VALUES (-2),(NULL),(2),(NULL); Warnings: Warning 1264 Out of range value for column 'c1' at row 1 @@ -423,6 +431,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -438,6 +447,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 2 auto_increment_offset 10 +wsrep_auto_increment_control ON INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL); SELECT * FROM t1; c1 @@ -456,6 +466,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -471,6 +482,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 2 auto_increment_offset 10 +wsrep_auto_increment_control ON INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL); ERROR HY000: Failed to read auto-increment value from storage engine SELECT * FROM t1; @@ -484,6 +496,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -499,6 +512,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 5 auto_increment_offset 7 +wsrep_auto_increment_control ON INSERT INTO t1 VALUES (NULL),(NULL), (NULL); ERROR HY000: Failed to read auto-increment value from storage engine SELECT * FROM t1; @@ -512,6 +526,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -531,6 +546,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 3 auto_increment_offset 3 +wsrep_auto_increment_control ON INSERT INTO t1 VALUES (NULL),(NULL), (NULL); SELECT * FROM t1; c1 @@ -548,6 +564,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON DROP TABLE IF EXISTS t1; Warnings: Note 1051 Unknown table 't1' @@ -566,6 +583,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 65535 auto_increment_offset 65535 +wsrep_auto_increment_control ON INSERT INTO t1 VALUES (NULL),(NULL); ERROR 22003: Out of range value for column 'c1' at row 1 SELECT * FROM t1; @@ -579,6 +597,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON CREATE TABLE t1 (c1 DOUBLE NOT NULL AUTO_INCREMENT, c2 INT, PRIMARY KEY (c1)) ENGINE=InnoDB; INSERT INTO t1 VALUES(NULL, 1); INSERT INTO t1 VALUES(NULL, 2); @@ -866,6 +885,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON CREATE TABLE t1 (c1 TINYINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; INSERT INTO t1 VALUES (1, NULL); INSERT INTO t1 VALUES (-1, 'innodb'); @@ -1256,6 +1276,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 256 +wsrep_auto_increment_control ON CREATE TABLE t1 (c1 TINYINT PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; INSERT INTO t1 VALUES (1, NULL); SHOW CREATE TABLE t1; @@ -1274,6 +1295,7 @@ SHOW VARIABLES LIKE "%auto_inc%"; Variable_name Value auto_increment_increment 1 auto_increment_offset 1 +wsrep_auto_increment_control ON CREATE TABLE t1 (c1 INT UNSIGNED PRIMARY KEY AUTO_INCREMENT, c2 VARCHAR(10)) ENGINE=InnoDB; INSERT INTO t1 VALUES (2147483648, 'a'); SHOW CREATE TABLE t1; diff --git a/mysql-test/suite/percona/innodb_sys_index.result b/mysql-test/suite/percona/innodb_sys_index.result index 8bf4fa745ba..756098d1127 100644 --- a/mysql-test/suite/percona/innodb_sys_index.result +++ b/mysql-test/suite/percona/innodb_sys_index.result @@ -3,7 +3,7 @@ Warnings: Note 1051 Unknown table 't1' select @@version_comment limit 1 ; @@version_comment -Source distribution +Source distribution, wsrep_<version> SELECT COUNT(*) FROM `information_schema`.`INNODB_SYS_INDEXES` ; CREATE TABLE test.t1 ( `a` SERIAL NOT NULL , `b` VARCHAR( 255 ) NOT NULL , INDEX ( `b` ) ) ENGINE = InnoDB ; SHOW TABLE STATUS FROM `information_schema` LIKE 'INNODB\_SYS\_INDEXES%' ; diff --git a/mysql-test/suite/percona/innodb_sys_index.test b/mysql-test/suite/percona/innodb_sys_index.test index 212baeda663..99d9e675148 100644 --- a/mysql-test/suite/percona/innodb_sys_index.test +++ b/mysql-test/suite/percona/innodb_sys_index.test @@ -5,6 +5,7 @@ drop table if exists t1; # # test for bug LP#875797 "Using 'innodb_sys_indexes' causes core dump" # +--replace_regex /wsrep_[0-9\.Xr]+/wsrep_<version>/ select @@version_comment limit 1 ; --disable_result_log SELECT COUNT(*) FROM `information_schema`.`INNODB_SYS_INDEXES` ; @@ -19,3 +20,4 @@ SELECT COUNT(*) FROM `information_schema`.`INNODB_SYS_INDEXES` ; drop table test.t1; SHOW TABLE STATUS FROM `information_schema` LIKE 'INNODB\_SYS\_INDEXES%' ; --enable_result_log + diff --git a/mysql-test/suite/sys_vars/r/all_vars.result b/mysql-test/suite/sys_vars/r/all_vars.result index 1bd4e394f6a..b61a8aabf08 100644 --- a/mysql-test/suite/sys_vars/r/all_vars.result +++ b/mysql-test/suite/sys_vars/r/all_vars.result @@ -10,5 +10,39 @@ there should be *no* long test name listed below: select distinct variable_name as `there should be *no* variables listed below:` from t2 left join t1 on variable_name=test_name where test_name is null; there should be *no* variables listed below: +innodb_disallow_writes +wsrep_auto_increment_control +wsrep_causal_reads +wsrep_certify_nonpk +wsrep_cluster_address +wsrep_cluster_name +wsrep_convert_lock_to_trx +wsrep_data_home_dir +wsrep_dbug_option +wsrep_debug +wsrep_drupal_282555_workaround +wsrep_forced_binlog_format +wsrep_log_conflicts +wsrep_max_ws_rows +wsrep_max_ws_size +wsrep_mysql_replication_bundle +wsrep_node_address +wsrep_node_incoming_address +wsrep_node_name +wsrep_notify_cmd +wsrep_on +wsrep_osu_method +wsrep_provider +wsrep_provider_options +wsrep_recover +wsrep_replicate_myisam +wsrep_retry_autocommit +wsrep_slave_threads +wsrep_sst_auth +wsrep_sst_donor +wsrep_sst_donor_rejects_queries +wsrep_sst_method +wsrep_sst_receive_address +wsrep_start_position drop table t1; drop table t2; diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index b6ee712ec28..05f98dfc4dc 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -1336,28 +1336,8 @@ explain select count(*) from information_schema.views; # # Bug#39955 SELECT on INFORMATION_SCHEMA.GLOBAL_VARIABLES takes too long # -set global init_connect="drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;\ -drop table if exists t1;drop table if exists t1;"; -select * from information_schema.global_variables where variable_name='init_connect'; +set global init_connect=repeat("drop table if exists t1;", 100); +select length(@@global.init_connect), length(variable_value) from information_schema.global_variables where variable_name='init_connect'; set global init_connect=""; # diff --git a/mysql-test/t/mysqld--help.test b/mysql-test/t/mysqld--help.test index 17969b65fb5..f8b75b1ec26 100644 --- a/mysql-test/t/mysqld--help.test +++ b/mysql-test/t/mysqld--help.test @@ -10,7 +10,7 @@ # force symbolic-links=0 (valgrind build has a different default) # -exec $MYSQLD_BOOTSTRAP_CMD --symbolic-links=0 --lower-case-table-names=1 --help --verbose > $MYSQL_TMP_DIR/mysqld--help.txt 2>&1; +exec $MYSQLD_BOOTSTRAP_CMD --symbolic-links=0 --lower-case-table-names=1 --help --verbose > $MYSQL_TMP_DIR/mysqld--help.txt; # The inline perl code below will copy $MYSQL_TMP_DIR/mysqld--help.txt # to output, but filter away some variable stuff (e.g. paths). diff --git a/mysys/default.c b/mysys/default.c index 70738e11d4b..36f33cd9796 100644 --- a/mysys/default.c +++ b/mysys/default.c @@ -87,6 +87,12 @@ static char my_defaults_extra_file_buffer[FN_REFLEN]; static my_bool defaults_already_read= FALSE; +#ifdef WITH_WSREP +/* The only purpose of this global array is to hold full name of my.cnf + * which seems to be otherwise unavailable */ +char wsrep_defaults_file[FN_REFLEN + 10]={0,}; +#endif /* WITH_WREP */ + /* Which directories are searched for options (and in which order) */ #define MAX_DEFAULT_DIRS 6 @@ -803,6 +809,12 @@ static int search_default_file_with_ext(Process_option_func opt_handler, if (!(fp= mysql_file_fopen(key_file_cnf, name, O_RDONLY, MYF(0)))) return 1; /* Ignore wrong files */ +#ifdef WITH_WSREP + /* make sure we do this only once - for top-level file */ + if ('\0' == wsrep_defaults_file[0]) + strncpy(wsrep_defaults_file, name, sizeof(wsrep_defaults_file) - 1); +#endif /* WITH_WSREP */ + while (mysql_file_fgets(buff, sizeof(buff) - 1, fp)) { line++; diff --git a/mysys/thr_lock.c b/mysys/thr_lock.c index 60e01974320..948a16d1032 100644 --- a/mysys/thr_lock.c +++ b/mysys/thr_lock.c @@ -94,7 +94,24 @@ be any number of TL_WRITE_CONCURRENT_INSERT locks aktive at the same time. my_bool thr_lock_inited=0; ulong locks_immediate = 0L, locks_waited = 0L; enum thr_lock_type thr_upgraded_concurrent_insert_lock = TL_WRITE; - +#ifdef WITH_WSREP +static wsrep_thd_is_brute_force_fun wsrep_thd_is_brute_force= NULL; +static wsrep_abort_thd_fun wsrep_abort_thd= NULL; +static my_bool wsrep_debug; +static my_bool wsrep_convert_LOCK_to_trx; +static wsrep_on_fun wsrep_on = NULL; + +void wsrep_thr_lock_init( + wsrep_thd_is_brute_force_fun bf_fun, wsrep_abort_thd_fun abort_fun, + my_bool debug, my_bool convert_LOCK_to_trx, wsrep_on_fun on_fun +) { + wsrep_thd_is_brute_force = bf_fun; + wsrep_abort_thd = abort_fun; + wsrep_debug = debug; + wsrep_convert_LOCK_to_trx= convert_LOCK_to_trx; + wsrep_on = on_fun; +} +#endif /* The following constants are only for debug output */ #define MAX_THREADS 1000 #define MAX_LOCKS 1000 @@ -1156,6 +1173,108 @@ static void sort_locks(THR_LOCK_DATA **data,uint count) } } +#ifdef WITH_WSREP +/* + * If brute force applier would need to wait for a thr lock, + * it needs to make sure that it will get the lock without (too much) + * delay. + * We identify here the owners of blocking locks and ask them to + * abort. We then put our lock request in the first place in the + * wait queue. When lock holders abort (one by one) the lock release + * algorithm should grant the lock to us. We rely on this and proceed + * to wait_for_locks(). + * wsrep_break_locks() should be called in all the cases, where lock + * wait would happen. + * + * TODO: current implementation might not cover all possible lock wait + * situations. This needs an review still. + * TODO: lock release, might favor some other lock (instead our bf). + * This needs an condition to check for bf locks first. + * TODO: we still have a debug fprintf, this should be removed + */ +static inline my_bool +wsrep_break_lock( + THR_LOCK_DATA *data, struct st_lock_list *lock_queue1, + struct st_lock_list *lock_queue2, struct st_lock_list *wait_queue) +{ + if (wsrep_on(data->owner->mysql_thd) && + wsrep_thd_is_brute_force && + wsrep_thd_is_brute_force(data->owner->mysql_thd)) + { + THR_LOCK_DATA *holder; + + /* if locking session conversion to transaction has been enabled, + we know that this conflicting lock must be read lock and furthermore, + lock holder is read-only. It is safe to wait for him. + */ +#ifdef TODO + if (wsrep_convert_LOCK_to_trx && + (THD*)(data->owner->mysql_thd)->in_lock_tables) + { + if (wsrep_debug) + fprintf(stderr,"WSREP wsrep_break_lock read lock untouched\n"); + return FALSE; + } +#endif + if (wsrep_debug) + fprintf(stderr,"WSREP wsrep_break_lock aborting locks\n"); + + /* aborting lock holder(s) here */ + for (holder=(lock_queue1) ? lock_queue1->data : NULL; + holder; + holder=holder->next) + { + if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd)) + { + wsrep_abort_thd(data->owner->mysql_thd, + holder->owner->mysql_thd, FALSE); + } + else + { + if (wsrep_debug) + fprintf(stderr,"WSREP wsrep_break_lock skipping BF lock conflict\n"); + return FALSE; + } + } + for (holder=(lock_queue2) ? lock_queue2->data : NULL; + holder; + holder=holder->next) + { + if (!wsrep_thd_is_brute_force(holder->owner->mysql_thd)) + { + wsrep_abort_thd(data->owner->mysql_thd, + holder->owner->mysql_thd, FALSE); + } + else + { + if (wsrep_debug) + fprintf(stderr,"WSREP wsrep_break_lock skipping BF lock conflict\n"); + return FALSE; + } + } + + /* Add our lock to the head of the wait queue */ + if (*(wait_queue->last)==wait_queue->data) + { + wait_queue->last=&data->next; + assert(wait_queue->data==0); + } + else + { + assert(wait_queue->data!=0); + wait_queue->data->prev=&data->next; + } + data->next=wait_queue->data; + data->prev=&wait_queue->data; + wait_queue->data=data; + data->cond=get_cond(); + + statistic_increment(locks_immediate,&THR_LOCK_lock); + return TRUE; + } + return FALSE; +} +#endif enum enum_thr_lock_result thr_multi_lock(THR_LOCK_DATA **data, uint count, THR_LOCK_INFO *owner, diff --git a/scripts/CMakeLists.txt b/scripts/CMakeLists.txt index 76e92899c2a..d11b6fa9bcc 100644 --- a/scripts/CMakeLists.txt +++ b/scripts/CMakeLists.txt @@ -313,6 +313,9 @@ IF(WIN32) INSTALL_SCRIPT(${CMAKE_CURRENT_BINARY_DIR}/${file}.pl COMPONENT Server_Scripts) ENDFOREACH() ELSE() + IF(WITH_WSREP) + SET(WSREP_BINARIES wsrep_sst_common wsrep_sst_mysqldump wsrep_sst_rsync wsrep_sst_xtrabackup) + ENDIF() # On Unix, most of the files end up in the bin directory SET(BIN_SCRIPTS msql2mysql @@ -329,6 +332,7 @@ ELSE() mysqldumpslow mysqld_multi mysqld_safe + ${WSREP_BINARIES} ) FOREACH(file ${BIN_SCRIPTS}) IF(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${file}.sh) diff --git a/scripts/mysqld_multi.sh b/scripts/mysqld_multi.sh index cd1b6fc18b7..52135071ac5 100644 --- a/scripts/mysqld_multi.sh +++ b/scripts/mysqld_multi.sh @@ -38,7 +38,7 @@ use Getopt::Long; use POSIX qw(strftime getcwd); $|=1; -$VER="2.16"; +$VER="2.20"; my @defaults_options; # Leading --no-defaults, --defaults-file, etc. @@ -138,6 +138,7 @@ sub main print "will be disabled\nand some will be enabled.\n\n"; } + init_log() if (!defined($opt_log)); $groupids = $ARGV[1]; if ($opt_version) { @@ -163,7 +164,6 @@ sub main !($ARGV[0] =~ m/^stop$/i) && !($ARGV[0] =~ m/^report$/i))); - init_log() if (!defined($opt_log)); if (!$opt_no_log) { w2log("$my_progname log file version $VER; run: ", @@ -206,9 +206,9 @@ sub main } } -# -# Quote word for shell -# +#### +#### Quote word for shell +#### sub quote_shell_word { @@ -218,6 +218,10 @@ sub quote_shell_word return $option; } +#### +#### get options for a group +#### + sub defaults_for_group { my ($group) = @_; @@ -319,8 +323,12 @@ sub report_mysqlds sub start_mysqlds() { - my (@groups, $com, $tmp, $i, @options, $j, $mysqld_found, $info_sent); + my (@groups, $com, $com2, $tmp, $i, @options, $j, $mysqld_found, + $info_sent, $curdir, $mysql_install_db, $srcdir, $basedir, + $datadir); + $mysql_install_db= undef(); + $srcdir= undef(); if (!$opt_no_log) { w2log("\nStarting MySQL servers\n","$opt_log",0,0); @@ -334,8 +342,9 @@ sub start_mysqlds() { @options = defaults_for_group($groups[$i]); - $basedir_found= 0; # The default - $mysqld_found= 1; # The default + my $basedir_found= 0; # The default + my $datadir_found= 0; # The default + my $mysqld_found= 1; # The default $mysqld_found= 0 if (!length($mysqld)); $com= "$mysqld"; for ($j = 0, $tmp= ""; defined($options[$j]); $j++) @@ -350,6 +359,47 @@ sub start_mysqlds() $com= $options[$j]; $mysqld_found= 1; } + elsif ("--mysql-install-db=" eq substr($options[$j], 0, 19)) + { + # mysql_install_db related option + + $options[$j]=~ s/\-\-mysql\-install\-db\=//; + $mysql_install_db= $options[$j]; + } + elsif ("--srcdir=" eq substr($options[$j], 0, 9)) + { + # mysql_install_db related option + + $options[$j]=~ s/\-\-srcdir\=//; + $srcdir= $options[$j]; + } + elsif ("--include-config=" eq substr($options[$j], 0, 17)) + { + $options[$j]=~ s/\-\-include\-config\=//; + $com2= "my_print_defaults --config-file=$options[$j] $groups[$i]"; + + # we need to reorder the array so that options in extra config file + # come in the middle. Needed if someone wants to overwrite an option + + my ($k, @tmp_array); + for ($k= $j + 1; defined($options[$k]); $k++) + { + push (@tmp_array, $options[$k]); + undef($options[$k]); + } + pop(@options); # pop out last null array element + push (@options, `$com2`); + chomp(@options); # new lines away + push (@options, @tmp_array); + } + elsif ("--datadir=" eq substr($options[$j], 0, 10)) + { + $datadir= $options[$j]; + $datadir =~ s/^--datadir=//; + $datadir_found= 1; + $options[$j]= quote_shell_word($options[$j]); + $tmp.= " $options[$j]"; + } elsif ("--basedir=" eq substr($options[$j], 0, 10)) { $basedir= $options[$j]; @@ -373,6 +423,25 @@ sub start_mysqlds() print "wanted mysqld binary.\n\n"; $info_sent= 1; } + if (defined($mysql_install_db)) + { + $com2= "$mysql_install_db"; + $com2.= " --srcdir=$srcdir" if (defined($srcdir)); + $com2.= " --datadir=$datadir" if ($datadir_found); + + if (-d "$datadir/mysql") + { + my $wstr= "WARNING: $datadir/mysql already exists. Not going to\n"; + $wstr.= "run $mysql_install_db on $datadir\n"; + print $wstr if ($opt_verbose); + w2log($wstr, 0, 0); + } + else + { + w2log("Installing databases on $datadir..\n", 0, 0); + `$com2`; + } + } $com.= $tmp; $com.= " >> $opt_log 2>&1" if (!$opt_no_log); $com.= " &"; @@ -442,7 +511,7 @@ sub stop_mysqlds() sub get_mysqladmin_options { my ($i, @groups)= @_; - my ($mysqladmin_found, $com, $tmp, $j); + my ($mysqladmin_found, $com, $com2, $tmp, $j); @options = defaults_for_group($groups[$i]); @@ -465,6 +534,25 @@ sub get_mysqladmin_options $com= $options[$j]; $mysqladmin_found= 1; } + elsif ("--include-config=" eq substr($options[$j], 0, 17)) + { + $options[$j]=~ s/\-\-include\-config\=//; + $com2= "my_print_defaults --config-file=$options[$j] $groups[$i]"; + + # we need to reorder the array so that options in extra config file + # come in the middle. Needed if someone wants to overwrite an option + + my ($k, @tmp_array); + for ($k= $j + 1; defined($options[$k]); $k++) + { + push (@tmp_array, $options[$k]); + undef($options[$k]); + } + pop(@options); # pop out last null array element + push (@options, `$com2`); + chomp(@options); # new lines away + push (@options, @tmp_array); + } elsif ((($options[$j] =~ m/^(\-\-socket\=)(.*)$/) && !$opt_tcp_ip) || ($options[$j] =~ m/^(\-\-port\=)(.*)$/)) { @@ -484,8 +572,11 @@ sub get_mysqladmin_options return $com; } -# Return a list of option files which can be opened. Similar, but not -# identical, to behavior of my_search_option_files() +#### +#### Return a list of option files which can be opened. Similar, but not +#### identical, to behavior of my_search_option_files() +#### + sub list_defaults_files { my %opt; @@ -507,9 +598,11 @@ sub list_defaults_files ($ENV{HOME} ? "$ENV{HOME}/.my.cnf" : undef)); } +#### +#### Takes a specification of GNRs (see --help), and returns a list of matching +#### groups which actually are mentioned in a relevant config file +#### -# Takes a specification of GNRs (see --help), and returns a list of matching -# groups which actually are mentioned in a relevant config file sub find_groups { my ($raw_gids) = @_; @@ -824,6 +917,17 @@ Using: @{[join ' ', @defaults_options]} question. This will be recognised as a special option and will not be passed to the mysqld. This will allow one to start different mysqld versions with mysqld_multi. +--include-config= An optional config file inside a group [mysqld#] which + the program is currently reading. It will read any extra + options of that group from additional file and insert them + where this option was found. Note that the group name + [mysqld#] must be the same in order for options to be found. +--mysql-install-db=... + mysql_install_db script to be used for creating internal + databases. Used when installing datadir for the first time. + This option will be skipped with info in the log file if + 'mysql' database already exists in the given datadir. +--srcdir=... srcdir argument for mysql_install_db script. Optional. --no-log Print to stdout instead of the log file. By default the log file is turned on. --password=... Password for mysqladmin user. diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh index 572a08781c8..7db2a5605e1 100644 --- a/scripts/mysqld_safe.sh +++ b/scripts/mysqld_safe.sh @@ -147,7 +147,7 @@ log_notice () { } eval_log_error () { - cmd="$1" + local cmd="$1" case $logging in file) cmd="$cmd >> "`shell_quote_string "$err_log"`" 2>&1" ;; syslog) @@ -183,6 +183,73 @@ shell_quote_string() { echo "$1" | sed -e 's,\([^a-zA-Z0-9/_.=-]\),\\\1,g' } +wsrep_pick_url() { + [ $# -eq 0 ] && return 0 + + log_error "WSREP: 'wsrep_urls' is DEPRECATED! Use wsrep_cluster_address to specify multiple addresses instead." + + if ! which nc >/dev/null; then + log_error "ERROR: nc tool not found in PATH! Make sure you have it installed." + return 1 + fi + + local url + # Assuming URL in the form scheme://host:port + # If host and port are not NULL, the liveness of URL is assumed to be tested + # If port part is absent, the url is returned literally and unconditionally + # If every URL has port but none is reachable, nothing is returned + for url in `echo $@ | sed s/,/\ /g` 0; do + local host=`echo $url | cut -d \: -f 2 | sed s/^\\\/\\\///` + local port=`echo $url | cut -d \: -f 3` + [ -z "$port" ] && break + nc -z "$host" $port >/dev/null && break + done + + if [ "$url" == "0" ]; then + log_error "ERROR: none of the URLs in '$@' is reachable." + return 1 + fi + + echo $url +} + +# Run mysqld with --wsrep-recover and parse recovered position from log. +# Position will be stored in wsrep_start_position_opt global. +wsrep_start_position_opt="" +wsrep_recover_position() { + local mysqld_cmd="$@" + local wr_logfile=$(mktemp) + local euid=$(id -u) + local ret=0 + + [ "$euid" = "0" ] && chown $user $wr_logfile + chmod 600 $wr_logfile + + log_notice "WSREP: Running position recovery with --log_error=$wr_logfile" + + eval_log_error $mysqld_cmd --log_error=$wr_logfile --wsrep-recover + + local rp="$(grep 'WSREP: Recovered position:' $wr_logfile)" + if [ -z "$rp" ]; then + local skipped="$(grep WSREP $wr_logfile | grep 'skipping position recovery')" + if [ -z "$skipped" ]; then + log_error "WSREP: Failed to recover position: " `cat $wr_logfile`; + ret=1 + else + log_notice "WSREP: Position recovery skipped" + fi + else + local start_pos="$(echo $rp | sed 's/.*WSREP\:\ Recovered\ position://' \ + | sed 's/^[ \t]*//')" + log_notice "WSREP: Recovered position $start_pos" + wsrep_start_position_opt="--wsrep_start_position=$start_pos" + fi + + rm $wr_logfile + + return $ret +} + parse_arguments() { # We only need to pass arguments through to the server if we don't # handle them here. So, we collect unrecognized options (passed on @@ -244,7 +311,13 @@ parse_arguments() { --skip-syslog) want_syslog=0 ;; --syslog-tag=*) syslog_tag="$val" ;; --timezone=*) TZ="$val"; export TZ; ;; - + --wsrep[-_]urls=*) wsrep_urls="$val"; ;; + --wsrep[-_]provider=*) + if test -n "$val" && test "$val" != "none" + then + wsrep_restart=1 + fi + ;; --help) usage ;; *) @@ -788,7 +861,8 @@ do done cmd="$cmd $args" # Avoid 'nohup: ignoring input' warning -test -n "$NOHUP_NICENESS" && cmd="$cmd < /dev/null" +nohup_redir="" +test -n "$NOHUP_NICENESS" && nohup_redir=" < /dev/null" log_notice "Starting $MYSQLD daemon with databases from $DATADIR" @@ -799,13 +873,31 @@ max_fast_restarts=5 # flag whether a usable sleep command exists have_sleep=1 +# maximum number of wsrep restarts +max_wsrep_restarts=0 + +# maximum number of wsrep restarts +max_wsrep_restarts=0 + while true do rm -f "$pid_file" # Some extra safety start_time=`date +%M%S` - eval_log_error "$cmd" + # this sets wsrep_start_position_opt + wsrep_recover_position "$cmd" + + [ $? -ne 0 ] && exit 1 # + + [ -n "$wsrep_urls" ] && url=`wsrep_pick_url $wsrep_urls` # check connect address + + if [ -z "$url" ] + then + eval_log_error "$cmd $wsrep_start_position_opt $nohup_redir" + else + eval_log_error "$cmd $wsrep_start_position_opt --wsrep_cluster_address=$url $nohup_redir" + fi if [ $want_syslog -eq 0 -a ! -f "$err_log" ]; then touch "$err_log" # hypothetical: log was renamed but not @@ -875,6 +967,20 @@ do I=`expr $I + 1` done fi + + if [ -n "$wsrep_restart" ] + then + if [ $wsrep_restart -le $max_wsrep_restarts ] + then + wsrep_restart=`expr $wsrep_restart + 1` + log_notice "WSREP: sleeping 15 seconds before restart" + sleep 15 + else + log_notice "WSREP: not restarting wsrep node automatically" + break + fi + fi + log_notice "mysqld restarted" if test -n "$CRASH_SCRIPT" then diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 0b4943851f0..ffd8fab16fd 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -13,6 +13,10 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +IF(WITH_WSREP) + SET(WSREP_INCLUDES ${CMAKE_SOURCE_DIR}/wsrep) +ENDIF() + INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/sql @@ -20,6 +24,7 @@ ${CMAKE_SOURCE_DIR}/regex ${ZLIB_INCLUDE_DIR} ${SSL_INCLUDE_DIRS} ${CMAKE_BINARY_DIR}/sql +${WSREP_INCLUDES} ) SET(GEN_SOURCES @@ -35,6 +40,18 @@ ADD_DEFINITIONS(-DMYSQL_SERVER -DHAVE_EVENT_SCHEDULER -DHAVE_POOL_OF_THREADS) IF(SSL_DEFINES) ADD_DEFINITIONS(${SSL_DEFINES}) ENDIF() +IF(WITH_WSREP) + SET(WSREP_SOURCES + wsrep_check_opts.cc + wsrep_hton.cc + wsrep_mysqld.cc + wsrep_notify.cc + wsrep_sst.cc + wsrep_utils.cc + wsrep_var.cc + ) + SET(WSREP_LIB wsrep) +ENDIF() SET (SQL_SOURCE ../sql-common/client.c derror.cc des_key_file.cc @@ -90,6 +107,7 @@ SET (SQL_SOURCE ../sql-common/mysql_async.c my_apc.cc my_apc.h rpl_gtid.cc + ${WSREP_SOURCES} ${GEN_SOURCES} ${MYSYS_LIBWRAP_SOURCE} ) @@ -109,6 +127,7 @@ DTRACE_INSTRUMENT(sql) TARGET_LINK_LIBRARIES(sql ${MYSQLD_STATIC_PLUGIN_LIBS} mysys dbug strings vio regex ${LIBWRAP} ${LIBCRYPT} ${LIBDL} + ${WSREP_LIB} ${SSL_LIBRARIES}) IF(WIN32) diff --git a/sql/events.cc b/sql/events.cc index b9c51b77f05..8645f64c4cd 100644 --- a/sql/events.cc +++ b/sql/events.cc @@ -1156,7 +1156,19 @@ end: close_mysql_tables(thd); DBUG_RETURN(ret); } +#ifdef WITH_WSREP +int wsrep_create_event_query(THD *thd, uchar** buf, uint* buf_len) +{ + String log_query; + if (create_query_string(thd, &log_query)) + { + WSREP_WARN("events create string failed: %s", thd->query()); + return 1; + } + return wsrep_to_buf_helper(thd, log_query.ptr(), log_query.length(), buf, buf_len); +} +#endif /* WITH_WSREP */ /** @} (End of group Event_Scheduler) */ diff --git a/sql/handler.cc b/sql/handler.cc index 7d97c197da5..8c8089a61fb 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -49,6 +49,9 @@ #include "../storage/maria/ha_maria.h" #endif +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif /* While we have legacy_db_type, we have this array to check for dups and to find handlerton from legacy_db_type. @@ -1296,7 +1299,11 @@ int ha_commit_trans(THD *thd, bool all) Free resources and perform other cleanup even for 'empty' transactions. */ if (is_real_trans) - thd->transaction.cleanup(); +#ifdef WITH_WSREP + thd->transaction.cleanup(thd); +#else + thd->transaction.cleanup(); +#endif /* WITH_WSREP */ DBUG_RETURN(0); } @@ -1324,7 +1331,12 @@ int ha_commit_trans(THD *thd, bool all) mdl_request.init(MDL_key::COMMIT, "", "", MDL_INTENTION_EXCLUSIVE, MDL_EXPLICIT); +#ifdef WITH_WSREP + if (!WSREP(thd) && + thd->mdl_context.acquire_lock(&mdl_request, +#else if (thd->mdl_context.acquire_lock(&mdl_request, +#endif /* WITH_WSREP */ thd->variables.lock_wait_timeout)) { ha_rollback_trans(thd, all); @@ -1371,6 +1383,19 @@ int ha_commit_trans(THD *thd, bool all) err= ht->prepare(ht, thd, all); status_var_increment(thd->status_var.ha_prepare_count); if (err) +#ifdef WITH_WSREP + if (WSREP(thd) && ht->db_type== DB_TYPE_WSREP) + { + error= 1; + /* avoid sending error, if we need to replay */ + if (thd->wsrep_conflict_state!= MUST_REPLAY) + { + my_error(ER_LOCK_DEADLOCK, MYF(0), err); + } + } + else + /* not wsrep hton, bail to native mysql behavior */ +#endif my_error(ER_ERROR_DURING_COMMIT, MYF(0), err); if (err) @@ -1382,6 +1407,13 @@ int ha_commit_trans(THD *thd, bool all) DEBUG_SYNC(thd, "ha_commit_trans_after_prepare"); DBUG_EXECUTE_IF("crash_commit_after_prepare", DBUG_SUICIDE();); +#ifdef WITH_WSREP + if (!error && wsrep_is_wsrep_xid(&thd->transaction.xid_state.xid)) + { + // xid was rewritten by wsrep + xid= wsrep_xid_seqno(&thd->transaction.xid_state.xid); + } +#endif // WITH_WSREP if (!is_real_trans) { error= commit_one_phase_2(thd, all, trans, is_real_trans); @@ -1470,6 +1502,18 @@ commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans) int error= 0; Ha_trx_info *ha_info= trans->ha_list, *ha_info_next; DBUG_ENTER("commit_one_phase_2"); +#ifdef WITH_WSREP +#ifdef WSREP_PROC_INFO + char info[64]= { 0, }; + snprintf (info, sizeof(info) - 1, "ha_commit_one_phase(%lld)", + (long long)thd->wsrep_trx_seqno); +#else + const char info[]="ha_commit_one_phase()"; +#endif /* WSREP_PROC_INFO */ + char* tmp_info= NULL; + if (WSREP(thd)) tmp_info= (char *)thd_proc_info(thd, info); +#endif /* WITH_WSREP */ + if (ha_info) { for (; ha_info; ha_info= ha_info_next) @@ -1498,7 +1542,14 @@ commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans) } /* Free resources and perform other cleanup even for 'empty' transactions. */ if (is_real_trans) +#ifdef WITH_WSREP + thd->transaction.cleanup(thd); +#else thd->transaction.cleanup(); +#endif /* WITH_WSREP */ +#ifdef WITH_WSREP + if (WSREP(thd)) thd_proc_info(thd, tmp_info); +#endif /* WITH_WSREP */ DBUG_RETURN(error); } @@ -1573,7 +1624,11 @@ int ha_rollback_trans(THD *thd, bool all) } /* Always cleanup. Even if nht==0. There may be savepoints. */ if (is_real_trans) +#ifdef WITH_WSREP + thd->transaction.cleanup(thd); +#else thd->transaction.cleanup(); +#endif /* WITH_WSREP */ if (all) thd->transaction_rollback_request= FALSE; @@ -1738,7 +1793,13 @@ static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin, got, hton_name(hton)->str); for (int i=0; i < got; i ++) { +#ifdef WITH_WSREP + my_xid x=(wsrep_is_wsrep_xid(&info->list[i]) ? + wsrep_xid_seqno(&info->list[i]) : + info->list[i].get_my_xid()); +#else my_xid x=info->list[i].get_my_xid(); +#endif /* WITH_WSREP */ if (!x) // not "mine" - that is generated by external TM { #ifndef DBUG_OFF @@ -2943,7 +3004,12 @@ int handler::update_auto_increment() variables->auto_increment_increment); auto_inc_intervals_count++; /* Row-based replication does not need to store intervals in binlog */ +#ifdef WITH_WSREP + if (((WSREP(thd) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()) && + !thd->is_current_stmt_binlog_format_row()) +#else if (mysql_bin_log.is_open() && !thd->is_current_stmt_binlog_format_row()) +#endif /* WITH_WSREP */ thd->auto_inc_intervals_in_cur_stmt_for_binlog.append(auto_inc_interval_for_cur_row.minimum(), auto_inc_interval_for_cur_row.values(), variables->auto_increment_increment); @@ -5320,7 +5386,11 @@ static bool check_table_binlog_row_based(THD *thd, TABLE *table) return (thd->is_current_stmt_binlog_format_row() && table->s->cached_row_logging_check && (thd->variables.option_bits & OPTION_BIN_LOG) && +#ifdef WITH_WSREP + ((WSREP(thd) && wsrep_emulate_bin_log) || mysql_bin_log.is_open())); +#else mysql_bin_log.is_open()); +#endif } @@ -5653,6 +5723,64 @@ void signal_log_not_needed(struct handlerton, char *log_file) } +#ifdef WITH_WSREP +/** + @details + This function makes the storage engine to force the victim transaction + to abort. Currently, only innodb has this functionality, but any SE + implementing the wsrep API should provide this service to support + multi-master operation. + + @param bf_thd brute force THD asking for the abort + @param victim_thd victim THD to be aborted + + @return + always 0 +*/ + +int ha_wsrep_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal) +{ + DBUG_ENTER("ha_wsrep_abort_transaction"); + if (!WSREP(bf_thd) && + !(wsrep_OSU_method_options == WSREP_OSU_RSU && + bf_thd->wsrep_exec_mode == TOTAL_ORDER)) { + DBUG_RETURN(0); + } + + handlerton *hton= installed_htons[DB_TYPE_INNODB]; + if (hton && hton->wsrep_abort_transaction) + { + hton->wsrep_abort_transaction(hton, bf_thd, victim_thd, signal); + } + else + { + WSREP_WARN("cannot abort InnoDB transaction"); + } + + DBUG_RETURN(0); +} + +void ha_wsrep_fake_trx_id(THD *thd) +{ + DBUG_ENTER("ha_wsrep_fake_trx_id"); + if (!WSREP(thd)) + { + DBUG_VOID_RETURN; + } + + handlerton *hton= installed_htons[DB_TYPE_INNODB]; + if (hton && hton->wsrep_fake_trx_id) + { + hton->wsrep_fake_trx_id(hton, thd); + } + else + { + WSREP_WARN("cannot get get fake InnoDB transaction ID"); + } + + DBUG_VOID_RETURN; +} +#endif /* WITH_WSREP */ #ifdef TRANS_LOG_MGM_EXAMPLE_CODE /* Example of transaction log management functions based on assumption that logs diff --git a/sql/handler.h b/sql/handler.h index a5fb0d8fd9d..c5639053fe2 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -372,6 +372,7 @@ enum legacy_db_type DB_TYPE_PBXT=23, DB_TYPE_MARIA=27, DB_TYPE_PERFORMANCE_SCHEMA=28, + DB_TYPE_WSREP=41, DB_TYPE_FIRST_DYNAMIC=42, DB_TYPE_DEFAULT=127 // Must be last }; @@ -1107,6 +1108,13 @@ struct handlerton enum handler_create_iterator_result (*create_iterator)(handlerton *hton, enum handler_iterator_type type, struct handler_iterator *fill_this_in); +#ifdef WITH_WSREP + int (*wsrep_abort_transaction)(handlerton *hton, THD *bf_thd, + THD *victim_thd, my_bool signal); + int (*wsrep_set_checkpoint)(handlerton *hton, const XID* xid); + int (*wsrep_get_checkpoint)(handlerton *hton, XID* xid); + void (*wsrep_fake_trx_id)(handlerton *hton, THD *thd); +#endif /* WITH_WSREP */ /* Optional clauses in the CREATE/ALTER TABLE */ @@ -3154,6 +3162,9 @@ bool key_uses_partial_cols(TABLE *table, uint keyno); extern const char *ha_row_type[]; extern MYSQL_PLUGIN_IMPORT const char *tx_isolation_names[]; extern MYSQL_PLUGIN_IMPORT const char *binlog_format_names[]; +#ifdef WITH_WSREP +extern MYSQL_PLUGIN_IMPORT const char *wsrep_binlog_format_names[]; +#endif /* WITH_WSREP */ extern TYPELIB tx_isolation_typelib; extern const char *myisam_stats_method_names[]; extern ulong total_ha, total_ha_2pc; @@ -3269,6 +3280,10 @@ int ha_enable_transaction(THD *thd, bool on); int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv); int ha_savepoint(THD *thd, SAVEPOINT *sv); int ha_release_savepoint(THD *thd, SAVEPOINT *sv); +#ifdef WITH_WSREP +int ha_wsrep_abort_transaction(THD *bf_thd, THD *victim_thd, my_bool signal); +void ha_wsrep_fake_trx_id(THD *thd); +#endif /* WITH_WSREP */ /* these are called by storage engines */ void trans_register_ha(THD *thd, bool all, handlerton *ht); @@ -3299,6 +3314,9 @@ int ha_binlog_end(THD *thd); #define ha_binlog_wait(a) do {} while (0) #define ha_binlog_end(a) do {} while (0) #endif +#ifdef WITH_WSREP +void wsrep_brute_force_aborts(); +#endif const char *get_canonical_filename(handler *file, const char *path, char *tmp_path); diff --git a/sql/item_func.cc b/sql/item_func.cc index d0fca63688a..a231b245b53 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -2596,7 +2596,19 @@ void Item_func_rand::seed_random(Item *arg) TODO: do not do reinit 'rand' for every execute of PS/SP if args[0] is a constant. */ +#ifdef WITH_WSREP + uint32 tmp; + if (WSREP(current_thd)) + { + if (current_thd->wsrep_exec_mode==REPL_RECV) + tmp= current_thd->wsrep_rand; + else + tmp= current_thd->wsrep_rand= (uint32) arg->val_int(); + } else + tmp= (uint32) arg->val_int(); +#else uint32 tmp= (uint32) arg->val_int(); +#endif /* WITH_WSREP */ my_rnd_init(rand, (uint32) (tmp*0x10001L+55555555L), (uint32) (tmp*0x10000001L)); } diff --git a/sql/lock.cc b/sql/lock.cc index 67c8b240c6f..b5605a0124a 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -84,6 +84,10 @@ #include <hash.h> #include <assert.h> +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif /* WITH_WSREP */ + /** @defgroup Locking Locking @{ @@ -314,6 +318,9 @@ bool mysql_lock_tables(THD *thd, MYSQL_LOCK *sql_lock, uint flags) /* Copy the lock data array. thr_multi_lock() reorders its contents. */ memcpy(sql_lock->locks + sql_lock->lock_count, sql_lock->locks, sql_lock->lock_count * sizeof(*sql_lock->locks)); +#ifdef WITH_WSREP + thd->lock_info.in_lock_tables= thd->in_lock_tables; +#endif /* Lock on the copied half of the lock data array. */ /* Lock on the copied half of the lock data array. */ rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->locks + sql_lock->lock_count, @@ -334,6 +341,9 @@ end: my_error(rc, MYF(0)); thd->set_time_after_lock(); +#ifdef WITH_WSREP + thd_proc_info(thd, "exit mysqld_lock_tables()"); +#endif /* WITH_WSREP */ DBUG_RETURN(rc); } @@ -1051,11 +1061,15 @@ void Global_read_lock::unlock_global_read_lock(THD *thd) { thd->mdl_context.release_lock(m_mdl_blocks_commits_lock); m_mdl_blocks_commits_lock= NULL; +#ifdef WITH_WSREP + wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; + wsrep->resume(wsrep); +#endif /* WITH_WSREP */ } thd->mdl_context.release_lock(m_mdl_global_shared_lock); m_mdl_global_shared_lock= NULL; m_state= GRL_NONE; - + DBUG_VOID_RETURN; } @@ -1083,6 +1097,20 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) If we didn't succeed lock_global_read_lock(), or if we already suceeded make_global_read_lock_block_commit(), do nothing. */ + +#ifdef WITH_WSREP + if (m_mdl_blocks_commits_lock) + { + WSREP_DEBUG("GRL was in block commit mode when entering " + "make_global_read_lock_block_commit"); + thd->mdl_context.release_lock(m_mdl_blocks_commits_lock); + m_mdl_blocks_commits_lock= NULL; + wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; + wsrep->resume(wsrep); + m_state= GRL_ACQUIRED; + } +#endif /* WITH_WSREP */ + if (m_state != GRL_ACQUIRED) DBUG_RETURN(0); @@ -1095,6 +1123,22 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) m_mdl_blocks_commits_lock= mdl_request.ticket; m_state= GRL_ACQUIRED_AND_BLOCKS_COMMIT; +#ifdef WITH_WSREP + long long ret = wsrep->pause(wsrep); + if (ret >= 0) + { + wsrep_locked_seqno= ret; + } + else if (ret != -ENOSYS) /* -ENOSYS - no provider */ + { + WSREP_ERROR("Failed to pause provider: %lld (%s)", -ret, strerror(-ret)); + + /* m_mdl_blocks_commits_lock is always NULL here */ + wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; + my_error(ER_LOCK_DEADLOCK, MYF(0)); + DBUG_RETURN(TRUE); + } +#endif /* WITH_WSREP */ DBUG_RETURN(FALSE); } diff --git a/sql/log.cc b/sql/log.cc index 6726be36e74..aba3c67583b 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -52,6 +52,9 @@ #include "sql_plugin.h" #include "rpl_handler.h" +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif /* WITH_WSREP */ #include "debug_sync.h" #include "sql_show.h" #include "my_pthread.h" @@ -509,6 +512,9 @@ private: }; handlerton *binlog_hton; +#ifdef WITH_WSREP +extern handlerton *wsrep_hton; +#endif bool LOGGER::is_log_table_enabled(uint log_table_type) { @@ -523,6 +529,134 @@ bool LOGGER::is_log_table_enabled(uint log_table_type) } } +#ifdef WITH_WSREP +IO_CACHE * get_trans_log(THD * thd) +{ + binlog_cache_mngr *cache_mngr = (binlog_cache_mngr*) + thd_get_ha_data(thd, binlog_hton); + if (cache_mngr) + { + return cache_mngr->get_binlog_cache_log(true); + } + else + { + WSREP_DEBUG("binlog cache not initialized, conn :%ld", thd->thread_id); + return NULL; + } +} + + +bool wsrep_trans_cache_is_empty(THD *thd) +{ + bool res= TRUE; + + if (thd_sql_command((const THD*) thd) != SQLCOM_SELECT) + res= FALSE; + else + { + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + if (cache_mngr) + { + res= cache_mngr->trx_cache.empty(); + } + } + return res; +} + +void thd_binlog_flush_pending_rows_event(THD *thd, bool stmt_end) +{ + thd->binlog_flush_pending_rows_event(stmt_end); +} +void thd_binlog_trx_reset(THD * thd) +{ + /* + todo: fix autocommit select to not call the caller + */ + if (thd_get_ha_data(thd, binlog_hton) != NULL) + { + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + if (cache_mngr) cache_mngr->reset(TRUE, TRUE); + } + thd->clear_binlog_table_maps(); +} + +void thd_binlog_rollback_stmt(THD * thd) +{ + WSREP_DEBUG("thd_binlog_rollback_stmt :%ld", thd->thread_id); + binlog_cache_mngr *const cache_mngr= + (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); + if (cache_mngr) cache_mngr->trx_cache.set_prev_position(MY_OFF_T_UNDEF); +} +/* + Write the contents of a cache to memory buffer. + + This function quite the same as MYSQL_BIN_LOG::write_cache(), + with the exception that here we write in buffer instead of log file. + */ + +int wsrep_write_cache(IO_CACHE *cache, uchar **buf, uint *buf_len) +{ + + if (reinit_io_cache(cache, READ_CACHE, 0, 0, 0)) + return ER_ERROR_ON_WRITE; + uint length= my_b_bytes_in_cache(cache); + long long total_length = 0; + uchar *buf_ptr = NULL; + + do + { + /* bail out if buffer grows too large + This is a temporary fix to avoid flooding replication + TODO: remove this check for 0.7.4 release + */ + if (total_length > wsrep_max_ws_size) + { + WSREP_WARN("transaction size limit (%lld) exceeded: %lld", + wsrep_max_ws_size, total_length); + if (reinit_io_cache(cache, WRITE_CACHE, 0, 0, 0)) + { + WSREP_WARN("failed to initialize io-cache"); + } + if (buf_ptr) my_free(*buf); + *buf_len = 0; + return ER_ERROR_ON_WRITE; + } + if (total_length > 0) + { + *buf_len += length; + *buf = (uchar *)my_realloc(*buf, total_length+length, MYF(0)); + if (!*buf) + { + WSREP_ERROR("io cache write problem: %d %d", *buf_len, length); + return ER_ERROR_ON_WRITE; + } + buf_ptr = *buf+total_length; + } + else + { + if (buf_ptr != NULL) + { + WSREP_ERROR("io cache alloc error: %d %d", *buf_len, length); + my_free(*buf); + } + if (length > 0) + { + *buf = (uchar *) my_malloc(length, MYF(0)); + buf_ptr = *buf; + *buf_len = length; + } + } + total_length += length; + + memcpy(buf_ptr, cache->read_pos, length); + cache->read_pos=cache->read_end; + } while ((cache->file >= 0) && (length= my_b_fill(cache))); + + return 0; +} +#endif /* Check if a given table is opened log table */ int check_if_log_table(size_t db_len, const char *db, size_t table_name_len, @@ -1555,7 +1689,11 @@ binlog_trans_log_savepos(THD *thd, my_off_t *pos) DBUG_ENTER("binlog_trans_log_savepos"); DBUG_ASSERT(pos != NULL); binlog_cache_mngr *const cache_mngr= thd->binlog_setup_trx_data(); +#ifdef WITH_WSREP + DBUG_ASSERT((WSREP(thd) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()); +#else DBUG_ASSERT(mysql_bin_log.is_open()); +#endif *pos= cache_mngr->trx_cache.get_byte_position(); DBUG_PRINT("return", ("*pos: %lu", (ulong) *pos)); DBUG_VOID_RETURN; @@ -1603,7 +1741,16 @@ binlog_trans_log_truncate(THD *thd, my_off_t pos) int binlog_init(void *p) { binlog_hton= (handlerton *)p; +#ifdef WITH_WSREP + if (WSREP_ON) + binlog_hton->state= SHOW_OPTION_YES; + else + { +#endif /* WITH_WSREP */ binlog_hton->state=opt_bin_log ? SHOW_OPTION_YES : SHOW_OPTION_NO; +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ binlog_hton->db_type=DB_TYPE_BINLOG; binlog_hton->savepoint_offset= sizeof(my_off_t); binlog_hton->close_connection= binlog_close_connection; @@ -1718,6 +1865,13 @@ static inline int binlog_commit_flush_stmt_cache(THD *thd, bool all, binlog_cache_mngr *cache_mngr) { +#ifdef WITH_WSREP + if (thd->wsrep_mysql_replicated > 0) + { + WSREP_DEBUG("avoiding binlog_commit_flush_trx_cache: %d", thd->wsrep_mysql_replicated); + return 0; + } +#endif Query_log_event end_evt(thd, STRING_WITH_LEN("COMMIT"), FALSE, TRUE, TRUE, 0); return (binlog_flush_cache(thd, cache_mngr, &end_evt, all, TRUE, FALSE)); @@ -1873,6 +2027,9 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all) DBUG_ENTER("binlog_commit"); binlog_cache_mngr *const cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); +#ifdef WITH_WSREP + if (!cache_mngr) DBUG_RETURN(0); +#endif /* WITH_WSREP */ DBUG_PRINT("debug", ("all: %d, in_transaction: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s", @@ -1929,6 +2086,9 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) int error= 0; binlog_cache_mngr *const cache_mngr= (binlog_cache_mngr*) thd_get_ha_data(thd, binlog_hton); +#ifdef WITH_WSREP + if (!cache_mngr) DBUG_RETURN(0); +#endif /* WITH_WSREP */ DBUG_PRINT("debug", ("all: %s, all.modified_non_trans_table: %s, stmt.modified_non_trans_table: %s", YESNO(all), @@ -1957,8 +2117,12 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) cache_mngr->reset(false, true); DBUG_RETURN(error); } - +#ifdef WITH_WSREP + if (!wsrep_emulate_bin_log && + mysql_bin_log.check_write_error(thd)) +#else if (mysql_bin_log.check_write_error(thd)) +#endif { /* "all == true" means that a "rollback statement" triggered the error and @@ -1988,12 +2152,12 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) if (ending_trans(thd, all) && ((thd->variables.option_bits & OPTION_KEEP_LOG) || (trans_has_updated_non_trans_table(thd) && - thd->variables.binlog_format == BINLOG_FORMAT_STMT) || + WSREP_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_STMT) || (cache_mngr->trx_cache.changes_to_non_trans_temp_table() && - thd->variables.binlog_format == BINLOG_FORMAT_MIXED) || + WSREP_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_MIXED) || (trans_has_updated_non_trans_table(thd) && ending_single_stmt_trans(thd,all) && - thd->variables.binlog_format == BINLOG_FORMAT_MIXED))) + WSREP_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_MIXED))) error= binlog_rollback_flush_trx_cache(thd, all, cache_mngr); /* Truncate the cache if: @@ -2007,9 +2171,9 @@ static int binlog_rollback(handlerton *hton, THD *thd, bool all) else if (ending_trans(thd, all) || (!(thd->variables.option_bits & OPTION_KEEP_LOG) && (!stmt_has_updated_non_trans_table(thd) || - thd->variables.binlog_format != BINLOG_FORMAT_STMT) && + WSREP_FORMAT(thd->variables.binlog_format) != BINLOG_FORMAT_STMT) && (!cache_mngr->trx_cache.changes_to_non_trans_temp_table() || - thd->variables.binlog_format != BINLOG_FORMAT_MIXED))) + WSREP_FORMAT(thd->variables.binlog_format) != BINLOG_FORMAT_MIXED))) error= binlog_truncate_trx_cache(thd, cache_mngr, all); } @@ -2103,6 +2267,9 @@ static int binlog_savepoint_set(handlerton *hton, THD *thd, void *sv) int error= 1; char buf[1024]; +#ifdef WITH_WSREP + if (wsrep_emulate_bin_log) DBUG_RETURN(0); +#endif /* WITH_WSREP */ String log_query(buf, sizeof(buf), &my_charset_bin); if (log_query.copy(STRING_WITH_LEN("SAVEPOINT "), &my_charset_bin) || append_identifier(thd, &log_query, @@ -2139,7 +2306,12 @@ static int binlog_savepoint_rollback(handlerton *hton, THD *thd, void *sv) non-transactional table. Otherwise, truncate the binlog cache starting from the SAVEPOINT command. */ +#ifdef WITH_WSREP + if (!wsrep_emulate_bin_log && + unlikely(trans_has_updated_non_trans_table(thd) || +#else if (unlikely(trans_has_updated_non_trans_table(thd) || +#endif (thd->variables.option_bits & OPTION_KEEP_LOG))) { char buf[1024]; @@ -5076,6 +5248,7 @@ binlog_cache_mngr *THD::binlog_setup_trx_data() DBUG_RETURN(cache_mngr); } + /* Function to start a statement and optionally a transaction for the binary log. @@ -5193,7 +5366,12 @@ int THD::binlog_write_table_map(TABLE *table, bool is_transactional, table->s->table_map_id)); /* Pre-conditions */ +#ifdef WITH_WSREP + DBUG_ASSERT(is_current_stmt_binlog_format_row() && + (WSREP_EMULATE_BINLOG(this) || mysql_bin_log.is_open())); +#else DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open()); +#endif DBUG_ASSERT(table->s->table_map_id != ULONG_MAX); Table_map_log_event @@ -5326,7 +5504,11 @@ MYSQL_BIN_LOG::flush_and_set_pending_rows_event(THD *thd, bool is_transactional) { DBUG_ENTER("MYSQL_BIN_LOG::flush_and_set_pending_rows_event(event)"); +#ifdef WITH_WSREP + DBUG_ASSERT(WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()); +#else DBUG_ASSERT(mysql_bin_log.is_open()); +#endif DBUG_PRINT("enter", ("event: 0x%lx", (long) event)); int error= 0; @@ -5645,7 +5827,11 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info, my_bool *with_annotate) mostly called if is_open() *was* true a few instructions before, but it could have changed since. */ +#ifdef WITH_WSREP + if ((WSREP(thd) && wsrep_emulate_bin_log) || is_open()) +#else if (likely(is_open())) +#endif { my_off_t UNINIT_VAR(my_org_b_tell); #ifdef HAVE_REPLICATION @@ -5827,6 +6013,35 @@ err: } } +#ifdef WITH_WSREP + if (WSREP(thd) && wsrep_incremental_data_collection && + (wsrep_emulate_bin_log || mysql_bin_log.is_open())) + { + DBUG_ASSERT(thd->wsrep_trx_handle.trx_id != (unsigned long)-1); + if (!error) + { + IO_CACHE* cache= get_trans_log(thd); + uchar* buf= NULL; + uint buf_len= 0; + + if (wsrep_emulate_bin_log) + thd->binlog_flush_pending_rows_event(false); + error= wsrep_write_cache(cache, &buf, &buf_len); + if (!error && buf_len > 0) + { + wsrep_status_t rc= wsrep->append_data(wsrep, + &thd->wsrep_trx_handle, + buf, buf_len); + if (rc != WSREP_OK) + { + sql_print_warning("WSREP: append_data() returned %d", rc); + error= 1; + } + } + if (buf_len) my_free(buf); + } + } +#endif /* WITH_WSREP */ DBUG_RETURN(error); } @@ -5982,6 +6197,14 @@ int MYSQL_BIN_LOG::rotate(bool force_rotate, bool* check_purge) { int error= 0; DBUG_ENTER("MYSQL_BIN_LOG::rotate"); +#ifdef WITH_WSREP + if (WSREP_ON && wsrep_to_isolation) + { + WSREP_DEBUG("avoiding binlog rotate due to TO isolation: %d", + wsrep_to_isolation); + DBUG_RETURN(0); + } +#endif //todo: fix the macro def and restore safe_mutex_assert_owner(&LOCK_log); *check_purge= false; @@ -6528,6 +6751,9 @@ MYSQL_BIN_LOG::write_transaction_to_binlog(THD *thd, Ha_trx_info *ha_info; DBUG_ENTER("MYSQL_BIN_LOG::write_transaction_to_binlog"); +#ifdef WITH_WSREP + if (wsrep_emulate_bin_log) DBUG_RETURN(0); +#endif /* WITH_WSREP */ entry.thd= thd; entry.cache_mngr= cache_mngr; entry.error= 0; @@ -8321,7 +8547,14 @@ TC_LOG_BINLOG::log_and_order(THD *thd, my_xid xid, bool all, binlog_cache_mngr *cache_mngr= thd->binlog_setup_trx_data(); if (!cache_mngr) +#ifdef WITH_WSREP + { + WSREP_DEBUG("Skipping empty log_xid: %s", thd->query()); + DBUG_RETURN(0); + } +#else DBUG_RETURN(0); +#endif /* WITH_WSREP */ cache_mngr->using_xa= TRUE; cache_mngr->xa_xid= xid; diff --git a/sql/log.h b/sql/log.h index 018ac64eff7..964d75916a9 100644 --- a/sql/log.h +++ b/sql/log.h @@ -95,7 +95,7 @@ public: int log_and_order(THD *thd, my_xid xid, bool all, bool need_prepare_ordered, bool need_commit_ordered) { - DBUG_ASSERT(0 /* Internal error - TC_LOG_DUMMY::log_and_order() called */); + //DBUG_ASSERT(0 /* Internal error - TC_LOG_DUMMY::log_and_order() called */); return 1; } int unlog(ulong cookie, my_xid xid) { return 0; } @@ -287,6 +287,12 @@ enum enum_log_state { LOG_OPENED, LOG_CLOSED, LOG_TO_BE_OPENED }; (mmap+fsync is two times faster than write+fsync) */ +#ifdef WITH_WSREP +extern my_bool wsrep_emulate_bin_log; +Log_event* wsrep_read_log_event( + char **arg_buf, size_t *arg_buf_len, + const Format_description_log_event *description_event); +#endif class MYSQL_LOG { public: @@ -952,12 +958,30 @@ public: }; enum enum_binlog_format { + /* + statement-based except for cases where only row-based can work (UUID() + etc): + */ BINLOG_FORMAT_MIXED= 0, ///< statement if safe, otherwise row - autodetected BINLOG_FORMAT_STMT= 1, ///< statement-based BINLOG_FORMAT_ROW= 2, ///< row-based BINLOG_FORMAT_UNSPEC=3 ///< thd_binlog_format() returns it when binlog is closed }; +#ifdef WITH_WSREP +IO_CACHE * get_trans_log(THD * thd); +bool wsrep_trans_cache_is_empty(THD *thd); +void thd_binlog_flush_pending_rows_event(THD *thd, bool stmt_end); +void thd_binlog_trx_reset(THD * thd); +void thd_binlog_rollback_stmt(THD * thd); +int wsrep_write_cache(IO_CACHE *cache, uchar **buf, uint *buf_len); + +#define WSREP_FORMAT(my_format) \ + ((wsrep_forced_binlog_format != BINLOG_FORMAT_UNSPEC) ? \ + wsrep_forced_binlog_format : my_format) +#else +#define WSREP_FORMAT(my_format) my_format +#endif int query_error_code(THD *thd, bool not_killed); uint purge_log_get_error_code(int res); diff --git a/sql/log_event.cc b/sql/log_event.cc index fce0130e8dd..2968764920e 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -49,6 +49,9 @@ #include "sql_show.h" // append_identifier #include <strfunc.h> +#if WITH_WSREP +#include "wsrep_mysqld.h" +#endif #endif /* MYSQL_CLIENT */ #include <base64.h> @@ -2873,7 +2876,9 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg, master_data_written(0) { time_t end_time; - +#ifdef WITH_WSREP + thd->wsrep_PA_safe= false; +#endif /* WITH_WSREP */ memset(&user, 0, sizeof(user)); memset(&host, 0, sizeof(host)); @@ -9078,10 +9083,21 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli) thd->variables.option_bits&= ~OPTION_RELAXED_UNIQUE_CHECKS; /* A small test to verify that objects have consistent types */ DBUG_ASSERT(sizeof(thd->variables.option_bits) == sizeof(OPTION_RELAXED_UNIQUE_CHECKS)); - if (open_and_lock_tables(thd, rli->tables_to_lock, FALSE, 0)) { uint actual_error= thd->stmt_da->sql_errno(); +#ifdef WITH_WSREP + if (WSREP(thd)) + { + WSREP_WARN("BF applier failed to open_and_lock_tables: %u, fatal: %d " + "wsrep = (exec_mode: %d conflict_state: %d seqno: %lld)", + thd->stmt_da->sql_errno(), + thd->is_fatal_error, + thd->wsrep_exec_mode, + thd->wsrep_conflict_state, + (long long)thd->wsrep_trx_seqno); + } +#endif if (thd->is_slave_error || thd->is_fatal_error) { /* @@ -10190,7 +10206,12 @@ check_table_map(Relay_log_info const *rli, RPL_TABLE_LIST *table_list) DBUG_ENTER("check_table_map"); enum_tbl_map_status res= OK_TO_PROCESS; +#ifdef WITH_WSREP + if ((rli->sql_thd->slave_thread /* filtering is for slave only */ || + (WSREP(rli->sql_thd) && rli->sql_thd->wsrep_applier)) && +#else if (rli->sql_thd->slave_thread /* filtering is for slave only */ && +#endif /* WITH_WSREP */ (!rli->mi->rpl_filter->db_ok(table_list->db) || (rli->mi->rpl_filter->is_on() && !rli->mi->rpl_filter->tables_ok("", table_list)))) res= FILTERED_OUT; @@ -10833,8 +10854,23 @@ int Write_rows_log_event::do_exec_row(const Relay_log_info *const rli) { DBUG_ASSERT(m_table != NULL); +#ifdef WITH_WSREP +#ifdef WSREP_PROC_INFO + char info[64]; + info[sizeof(info) - 1] = '\0'; + snprintf(info, sizeof(info) - 1, "Write_rows_log_event::write_row(%lld)", + (long long) thd->wsrep_trx_seqno); + const char* tmp = (WSREP(thd)) ? thd_proc_info(thd, info) : NULL; +#else + const char* tmp = (WSREP(thd)) ? + thd_proc_info(thd,"Write_rows_log_event::write_row()") : NULL; +#endif /* WSREP_PROC_INFO */ +#endif /* WITH_WSREP */ int error= write_row(rli, slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT); +#ifdef WITH_WSREP + if (WSREP(thd)) thd_proc_info(thd, tmp); +#endif /* WITH_WSREP */ if (error && !thd->is_error()) { DBUG_ASSERT(0); @@ -11499,14 +11535,39 @@ int Delete_rows_log_event::do_exec_row(const Relay_log_info *const rli) int error; DBUG_ASSERT(m_table != NULL); +#ifdef WITH_WSREP +#ifdef WSREP_PROC_INFO + char info[64]; + info[sizeof(info) - 1] = '\0'; + snprintf(info, sizeof(info) - 1, "Delete_rows_log_event::find_row(%lld)", + (long long) thd->wsrep_trx_seqno); + const char* tmp = (WSREP(thd)) ? thd_proc_info(thd, info) : NULL; +#else + const char* tmp = (WSREP(thd)) ? + thd_proc_info(thd,"Delete_rows_log_event::find_row()") : NULL; +#endif /* WSREP_PROC_INFO */ +#endif /* WITH_WSREP */ if (!(error= find_row(rli))) { /* Delete the record found, located in record[0] */ +#ifdef WITH_WSREP +#ifdef WSREP_PROC_INFO + snprintf(info, sizeof(info) - 1, + "Delete_rows_log_event::ha_delete_row(%lld)", + (long long) thd->wsrep_trx_seqno); + if (WSREP(thd)) thd_proc_info(thd, info); +#else + if (WSREP(thd)) thd_proc_info(thd,"Delete_rows_log_event::ha_delete_row()"); +#endif /* WSREP_PROC_INFO */ +#endif /* WITH_WSREP */ error= m_table->file->ha_delete_row(m_table->record[0]); m_table->file->ha_index_or_rnd_end(); } +#ifdef WITH_WSREP + if (WSREP(thd)) thd_proc_info(thd, tmp); +#endif /* WITH_WSREP */ return error; } @@ -11624,6 +11685,18 @@ Update_rows_log_event::do_exec_row(const Relay_log_info *const rli) { DBUG_ASSERT(m_table != NULL); +#ifdef WITH_WSREP +#ifdef WSREP_PROC_INFO + char info[64]; + info[sizeof(info) - 1] = '\0'; + snprintf(info, sizeof(info) - 1, "Update_rows_log_event::find_row(%lld)", + (long long) thd->wsrep_trx_seqno); + const char* tmp = (WSREP(thd)) ? thd_proc_info(thd, info) : NULL; +#else + const char* tmp = (WSREP(thd)) ? + thd_proc_info(thd,"Update_rows_log_event::find_row()") : NULL; +#endif /* WSREP_PROC_INFO */ +#endif /* WITH_WSREP */ int error= find_row(rli); if (error) { @@ -11650,6 +11723,17 @@ Update_rows_log_event::do_exec_row(const Relay_log_info *const rli) store_record(m_table,record[1]); m_curr_row= m_curr_row_end; +#ifdef WITH_WSREP +#ifdef WSREP_PROC_INFO + snprintf(info, sizeof(info) - 1, + "Update_rows_log_event::unpack_current_row(%lld)", + (long long) thd->wsrep_trx_seqno); + if (WSREP(thd)) thd_proc_info(thd, info); +#else + if (WSREP(thd)) + thd_proc_info(thd,"Update_rows_log_event::unpack_current_row()"); +#endif /* WSREP_PROC_INFO */ +#endif /* WITH_WSREP */ /* this also updates m_curr_row_end */ if ((error= unpack_current_row(rli))) goto err; @@ -11668,10 +11752,23 @@ Update_rows_log_event::do_exec_row(const Relay_log_info *const rli) DBUG_DUMP("new values", m_table->record[0], m_table->s->reclength); #endif +#ifdef WITH_WSREP +#ifdef WSREP_PROC_INFO + snprintf(info, sizeof(info) - 1, + "Update_rows_log_event::ha_update_row(%lld)", + (long long) thd->wsrep_trx_seqno); + if (WSREP(thd)) thd_proc_info(thd, info); +#else + if (WSREP(thd)) thd_proc_info(thd,"Update_rows_log_event::ha_update_row()"); +#endif /* WSREP_PROC_INFO */ +#endif /* WITH_WSREP */ error= m_table->file->ha_update_row(m_table->record[1], m_table->record[0]); if (error == HA_ERR_RECORD_IS_THE_SAME) error= 0; +#ifdef WITH_WSREP + if (WSREP(thd)) thd_proc_info(thd, tmp); +#endif /* WITH_WSREP */ err: m_table->file->ha_index_or_rnd_end(); return error; @@ -11756,6 +11853,48 @@ void Incident_log_event::pack_info(THD *thd, Protocol *protocol) protocol->store(buf, bytes, &my_charset_bin); } #endif +#if WITH_WSREP && !defined(MYSQL_CLIENT) +Format_description_log_event *wsrep_format_desc; // TODO: free them at the end +/* + read the first event from (*buf). The size of the (*buf) is (*buf_len). + At the end (*buf) is shitfed to point to the following event or NULL and + (*buf_len) will be changed to account just being read bytes of the 1st event. +*/ +#define WSREP_MAX_ALLOWED_PACKET 1024*1024*1024 // current protocol max + +Log_event* wsrep_read_log_event( + char **arg_buf, size_t *arg_buf_len, + const Format_description_log_event *description_event) +{ + DBUG_ENTER("wsrep_read_log_event"); + char *head= (*arg_buf); + + uint data_len = uint4korr(head + EVENT_LEN_OFFSET); + char *buf= (*arg_buf); + const char *error= 0; + Log_event *res= 0; + + if (data_len > WSREP_MAX_ALLOWED_PACKET) + { + error = "Event too big"; + goto err; + } + + res= Log_event::read_log_event(buf, data_len, &error, description_event, FALSE); + +err: + if (!res) + { + DBUG_ASSERT(error != 0); + sql_print_error("Error in Log_event::read_log_event(): " + "'%s', data_len: %d, event_type: %d", + error,data_len,head[EVENT_TYPE_OFFSET]); + } + (*arg_buf)+= data_len; + (*arg_buf_len)-= data_len; + DBUG_RETURN(res); +} +#endif #ifdef MYSQL_CLIENT diff --git a/sql/mdl.cc b/sql/mdl.cc index 9402de02c36..e7321d35e77 100644 --- a/sql/mdl.cc +++ b/sql/mdl.cc @@ -22,6 +22,17 @@ #include <mysql/plugin.h> #include <mysql/service_thd_wait.h> #include <mysql/psi/mysql_stage.h> +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +extern "C" my_thread_id wsrep_thd_thread_id(THD *thd); +extern "C" char *wsrep_thd_query(THD *thd); +void sql_print_information(const char *format, ...) + ATTRIBUTE_FORMAT(printf, 1, 2); + +extern bool +wsrep_grant_mdl_exception(MDL_context *requestor_ctx, + MDL_ticket *ticket); +#endif /* WITH_WSREP */ #ifdef HAVE_PSI_INTERFACE static PSI_mutex_key key_MDL_map_mutex; @@ -1311,11 +1322,54 @@ void MDL_lock::Ticket_list::add_ticket(MDL_ticket *ticket) called by other threads. */ DBUG_ASSERT(ticket->get_lock()); +#ifdef WITH_WSREP + if ((this == &(ticket->get_lock()->m_waiting)) && + wsrep_thd_is_brute_force((void *)(ticket->get_ctx()->get_thd()))) + { + Ticket_iterator itw(ticket->get_lock()->m_waiting); + Ticket_iterator itg(ticket->get_lock()->m_granted); + + MDL_ticket *waiting, *granted; + MDL_ticket *prev=NULL; + bool added= false; + + while ((waiting= itw++) && !added) + { + if (!wsrep_thd_is_brute_force((void *)(waiting->get_ctx()->get_thd()))) + { + WSREP_DEBUG("MDL add_ticket inserted before: %lu %s", + wsrep_thd_thread_id(waiting->get_ctx()->get_thd()), + wsrep_thd_query(waiting->get_ctx()->get_thd())); + m_list.insert_after(prev, ticket); + added= true; + } + prev= waiting; + } + if (!added) m_list.push_back(ticket); + + while ((granted= itg++)) + { + if (granted->get_ctx() != ticket->get_ctx() && + granted->is_incompatible_when_granted(ticket->get_type())) + { + if (!wsrep_grant_mdl_exception(ticket->get_ctx(), granted)) + { + WSREP_DEBUG("MDL victim killed at add_ticket"); + } + } + } + } + else + { +#endif /* WITH_WSREP */ /* Add ticket to the *back* of the queue to ensure fairness among requests with the same priority. */ m_list.push_back(ticket); +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ m_bitmap|= MDL_BIT(ticket->get_type()); } @@ -1621,7 +1675,6 @@ MDL_object_lock::m_waiting_incompatible[MDL_TYPE_END] = 0 }; - /** Check if request for the metadata lock can be satisfied given its current state. @@ -1646,6 +1699,9 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, bool can_grant= FALSE; bitmap_t waiting_incompat_map= incompatible_waiting_types_bitmap()[type_arg]; bitmap_t granted_incompat_map= incompatible_granted_types_bitmap()[type_arg]; +#ifdef WITH_WSREP + bool wsrep_can_grant= TRUE; +#endif /* WITH_WSREP */ /* New lock request can be satisfied iff: @@ -1668,12 +1724,59 @@ MDL_lock::can_grant_lock(enum_mdl_type type_arg, { if (ticket->get_ctx() != requestor_ctx && ticket->is_incompatible_when_granted(type_arg)) +#ifdef WITH_WSREP + { + if (wsrep_thd_is_brute_force((void *)(requestor_ctx->get_thd())) && + key.mdl_namespace() == MDL_key::GLOBAL) + { + WSREP_DEBUG("global lock granted for BF: %lu %s", + wsrep_thd_thread_id(requestor_ctx->get_thd()), + wsrep_thd_query(requestor_ctx->get_thd())); + can_grant = true; + } + else if (!wsrep_grant_mdl_exception(requestor_ctx, ticket)) + { + wsrep_can_grant= FALSE; + if (wsrep_log_conflicts) + { + MDL_lock * lock = ticket->get_lock(); + WSREP_INFO( + "MDL conflict db=%s table=%s ticket=%d solved by %s", + lock->key.db_name(), lock->key.name(), ticket->get_type(), "abort" + ); + } + } + else + { + can_grant= TRUE; + } + } +#else break; +#endif /* WITH_WSREP */ } +#ifdef WITH_WSREP + if ((ticket == NULL) && wsrep_can_grant) +#else if (ticket == NULL) /* Incompatible locks are our own. */ +#endif /* WITH_WSREP */ + can_grant= TRUE; } } +#ifdef WITH_WSREP + else + { + if (wsrep_thd_is_brute_force((void *)(requestor_ctx->get_thd())) && + key.mdl_namespace() == MDL_key::GLOBAL) + { + WSREP_DEBUG("global lock granted for BF (waiting queue): %lu %s", + wsrep_thd_thread_id(requestor_ctx->get_thd()), + wsrep_thd_query(requestor_ctx->get_thd())); + can_grant = true; + } + } +#endif /* WITH_WSREP */ return can_grant; } @@ -3019,3 +3122,33 @@ void MDL_context::set_transaction_duration_for_all_locks() ticket->m_duration= MDL_TRANSACTION; #endif } +#ifdef WITH_WSREP +void MDL_ticket::wsrep_report(bool debug) +{ + if (debug) + { + WSREP_DEBUG("MDL ticket: type: %s space: %s db: %s name: %s (%s)", + (get_type() == MDL_INTENTION_EXCLUSIVE) ? "intention exclusive" : + ((get_type() == MDL_SHARED) ? "shared" : + ((get_type() == MDL_SHARED_HIGH_PRIO ? "shared high prio" : + ((get_type() == MDL_SHARED_READ) ? "shared read" : + ((get_type() == MDL_SHARED_WRITE) ? "shared write" : + ((get_type() == MDL_SHARED_NO_WRITE) ? "shared no write" : + ((get_type() == MDL_SHARED_NO_READ_WRITE) ? "shared no read write" : + ((get_type() == MDL_EXCLUSIVE) ? "exclusive" : + "UNKNOWN")))))))), + (m_lock->key.mdl_namespace() == MDL_key::GLOBAL) ? "GLOBAL" : + ((m_lock->key.mdl_namespace() == MDL_key::SCHEMA) ? "SCHEMA" : + ((m_lock->key.mdl_namespace() == MDL_key::TABLE) ? "TABLE" : + ((m_lock->key.mdl_namespace() == MDL_key::TABLE) ? "FUNCTION" : + ((m_lock->key.mdl_namespace() == MDL_key::TABLE) ? "PROCEDURE" : + ((m_lock->key.mdl_namespace() == MDL_key::TABLE) ? "TRIGGER" : + ((m_lock->key.mdl_namespace() == MDL_key::TABLE) ? "EVENT" : + ((m_lock->key.mdl_namespace() == MDL_key::COMMIT) ? "COMMIT" : + (char *)"UNKNOWN"))))))), + m_lock->key.db_name(), + m_lock->key.name(), + m_lock->key.get_wait_state_name()); + } +} +#endif /* WITH_WSREP */ diff --git a/sql/mdl.h b/sql/mdl.h index 944c6bb6349..e4986aaba95 100644 --- a/sql/mdl.h +++ b/sql/mdl.h @@ -504,6 +504,9 @@ public: MDL_ticket *next_in_lock; MDL_ticket **prev_in_lock; public: +#ifdef WITH_WSREP + void wsrep_report(bool debug); +#endif /* WITH_WSREP */ bool has_pending_conflicting_lock() const; MDL_context *get_ctx() const { return m_ctx; } diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 0a49eb0c7ee..1b61167cf3b 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -73,6 +73,10 @@ #include "scheduler.h" #include <waiting_threads.h> #include "debug_sync.h" +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +ulong wsrep_running_threads = 0; // # of currently running wsrep threads +#endif #include "sql_callback.h" #include "threadpool.h" @@ -367,6 +371,9 @@ static DYNAMIC_ARRAY all_options; /* Global variables */ +#ifdef WITH_WSREP +ulong my_bind_addr; +#endif /* WITH_WSREP */ bool opt_bin_log, opt_bin_log_used=0, opt_ignore_builtin_innodb= 0; my_bool opt_log, opt_slow_log, debug_assert_if_crashed_table= 0, opt_help= 0, opt_abort; ulonglong log_output_options; @@ -459,6 +466,10 @@ ulong opt_binlog_rows_event_max_size; my_bool opt_master_verify_checksum= 0; my_bool opt_slave_sql_verify_checksum= 1; const char *binlog_format_names[]= {"MIXED", "STATEMENT", "ROW", NullS}; +#ifdef WITH_WSREP +const char *wsrep_binlog_format_names[]= + {"MIXED", "STATEMENT", "ROW", "NONE", NullS}; +#endif /*WITH_WSREP */ #ifdef HAVE_INITGROUPS volatile sig_atomic_t calling_initgroups= 0; /**< Used in SIGSEGV handler. */ #endif @@ -704,6 +715,22 @@ mysql_cond_t COND_server_started; int mysqld_server_started=0, mysqld_server_initialized= 0; File_parser_dummy_hook file_parser_dummy_hook; +#ifdef WITH_WSREP +mysql_mutex_t LOCK_wsrep_ready; +mysql_cond_t COND_wsrep_ready; +mysql_mutex_t LOCK_wsrep_sst; +mysql_cond_t COND_wsrep_sst; +mysql_mutex_t LOCK_wsrep_sst_init; +mysql_cond_t COND_wsrep_sst_init; +mysql_mutex_t LOCK_wsrep_rollback; +mysql_cond_t COND_wsrep_rollback; +wsrep_aborting_thd_t wsrep_aborting_thd= NULL; +mysql_mutex_t LOCK_wsrep_replaying; +mysql_cond_t COND_wsrep_replaying; +mysql_mutex_t LOCK_wsrep_slave_threads; +int wsrep_replaying= 0; +static void wsrep_close_threads(THD* thd); +#endif /* replication parameters, if master_host is not NULL, we are a slave */ uint report_port= 0; @@ -842,6 +869,12 @@ PSI_mutex_key key_BINLOG_LOCK_index, key_BINLOG_LOCK_xid_list, key_LOCK_error_messages, key_LOG_INFO_lock, key_LOCK_thread_count, key_LOCK_thread_cache, key_PARTITION_LOCK_auto_inc; +#ifdef WITH_WSREP +PSI_mutex_key key_LOCK_wsrep_rollback, key_LOCK_wsrep_thd, + key_LOCK_wsrep_replaying, key_LOCK_wsrep_ready, key_LOCK_wsrep_sst, + key_LOCK_wsrep_sst_thread, key_LOCK_wsrep_sst_init, + key_LOCK_wsrep_slave_threads; +#endif PSI_mutex_key key_RELAYLOG_LOCK_index; PSI_mutex_key key_LOCK_slave_state, key_LOCK_binlog_state; @@ -914,6 +947,17 @@ static PSI_mutex_info all_server_mutexes[]= { &key_LOCK_prepare_ordered, "LOCK_prepare_ordered", PSI_FLAG_GLOBAL}, { &key_LOCK_commit_ordered, "LOCK_commit_ordered", PSI_FLAG_GLOBAL}, { &key_LOG_INFO_lock, "LOG_INFO::lock", 0}, +#ifdef WITH_WSREP + { &key_LOCK_wsrep_ready, "LOCK_wsrep_ready", PSI_FLAG_GLOBAL}, + { &key_LOCK_wsrep_sst, "LOCK_wsrep_sst", PSI_FLAG_GLOBAL}, + { &key_LOCK_wsrep_sst_thread, "wsrep_sst_thread", 0}, + { &key_LOCK_wsrep_sst_init, "LOCK_wsrep_sst_init", PSI_FLAG_GLOBAL}, + { &key_LOCK_wsrep_sst, "LOCK_wsrep_sst", PSI_FLAG_GLOBAL}, + { &key_LOCK_wsrep_rollback, "LOCK_wsrep_rollback", PSI_FLAG_GLOBAL}, + { &key_LOCK_wsrep_thd, "THD::LOCK_wsrep_thd", 0}, + { &key_LOCK_wsrep_replaying, "LOCK_wsrep_replaying", PSI_FLAG_GLOBAL}, + { &key_LOCK_wsrep_slave_threads, "LOCK_wsrep_slave_threads", PSI_FLAG_GLOBAL}, +#endif { &key_LOCK_thread_count, "LOCK_thread_count", PSI_FLAG_GLOBAL}, { &key_LOCK_thread_cache, "LOCK_thread_cache", PSI_FLAG_GLOBAL}, { &key_PARTITION_LOCK_auto_inc, "HA_DATA_PARTITION::LOCK_auto_inc", 0}, @@ -957,6 +1001,11 @@ PSI_cond_key key_BINLOG_COND_xid_list, key_BINLOG_update_cond, key_TABLE_SHARE_cond, key_user_level_lock_cond, key_COND_thread_count, key_COND_thread_cache, key_COND_flush_thread_cache, key_BINLOG_COND_queue_busy; +#ifdef WITH_WSREP +PSI_cond_key key_COND_wsrep_rollback, key_COND_wsrep_thd, + key_COND_wsrep_replaying, key_COND_wsrep_ready, key_COND_wsrep_sst, + key_COND_wsrep_sst_init, key_COND_wsrep_sst_thread; +#endif /* WITH_WSREP */ PSI_cond_key key_RELAYLOG_update_cond, key_COND_wakeup_ready; PSI_cond_key key_RELAYLOG_COND_queue_busy; PSI_cond_key key_TC_LOG_MMAP_COND_queue_busy; @@ -999,6 +1048,15 @@ static PSI_cond_info all_server_conds[]= { &key_user_level_lock_cond, "User_level_lock::cond", 0}, { &key_COND_thread_count, "COND_thread_count", PSI_FLAG_GLOBAL}, { &key_COND_thread_cache, "COND_thread_cache", PSI_FLAG_GLOBAL}, +#ifdef WITH_WSREP + { &key_COND_wsrep_ready, "COND_wsrep_ready", PSI_FLAG_GLOBAL}, + { &key_COND_wsrep_sst, "COND_wsrep_sst", PSI_FLAG_GLOBAL}, + { &key_COND_wsrep_sst_init, "COND_wsrep_sst_init", PSI_FLAG_GLOBAL}, + { &key_COND_wsrep_sst_thread, "wsrep_sst_thread", 0}, + { &key_COND_wsrep_rollback, "COND_wsrep_rollback", PSI_FLAG_GLOBAL}, + { &key_COND_wsrep_thd, "THD::COND_wsrep_thd", 0}, + { &key_COND_wsrep_replaying, "COND_wsrep_replaying", PSI_FLAG_GLOBAL}, +#endif { &key_COND_flush_thread_cache, "COND_flush_thread_cache", PSI_FLAG_GLOBAL} }; @@ -1559,6 +1617,11 @@ static void close_connections(void) if (tmp->slave_thread) continue; +#ifdef WITH_WSREP + /* skip wsrep system threads as well */ + if (WSREP(tmp) && (tmp->wsrep_exec_mode==REPL_RECV || tmp->wsrep_applier)) + continue; +#endif tmp->killed= KILL_SERVER_HARD; MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp)); mysql_mutex_lock(&tmp->LOCK_thd_data); @@ -1635,6 +1698,33 @@ static void close_connections(void) close_connection(tmp,ER_SERVER_SHUTDOWN); } #endif +#ifdef WITH_WSREP + /* + * TODO: this code block may turn out redundant. wsrep->disconnect() + * should terminate slave threads gracefully, and we don't need + * to signal them here. + * The code here makes sure mysqld will not hang during shutdown + * even if wsrep provider has problems in shutting down. + */ + if (WSREP(tmp) && tmp->wsrep_exec_mode==REPL_RECV) + { + sql_print_information("closing wsrep system thread"); + tmp->killed= KILL_CONNECTION; + MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (tmp)); + if (tmp->mysys_var) + { + tmp->mysys_var->abort=1; + mysql_mutex_lock(&tmp->mysys_var->mutex); + if (tmp->mysys_var->current_cond) + { + mysql_mutex_lock(tmp->mysys_var->current_mutex); + mysql_cond_broadcast(tmp->mysys_var->current_cond); + mysql_mutex_unlock(tmp->mysys_var->current_mutex); + } + mysql_mutex_unlock(&tmp->mysys_var->mutex); + } + } +#endif DBUG_PRINT("quit",("Unlocking LOCK_thread_count")); mysql_mutex_unlock(&LOCK_thread_count); } @@ -1787,8 +1877,14 @@ static void __cdecl kill_server(int sig_ptr) } } #endif +#ifdef WITH_WSREP + if (WSREP_ON) wsrep_stop_replication(NULL); +#endif close_connections(); +#ifdef WITH_WSREP + if (WSREP_ON) wsrep_deinit(); +#endif if (sig != MYSQL_KILL_SIGNAL && sig != 0) unireg_abort(1); /* purecov: inspected */ @@ -1883,6 +1979,21 @@ extern "C" void unireg_abort(int exit_code) usage(); if (exit_code) sql_print_error("Aborting\n"); +#ifdef WITH_WSREP + if (wsrep) + { + /* This is an abort situation, we cannot expect to gracefully close all + * wsrep threads here, we can only diconnect from service */ + wsrep_close_client_connections(FALSE); + shutdown_in_progress= 1; + THD* thd(0); + wsrep->disconnect(wsrep); + WSREP_INFO("Service disconnected."); + wsrep_close_threads(thd); /* this won't close all threads */ + sleep(1); /* so give some time to exit for those which can */ + WSREP_INFO("Some threads may fail to exit."); + } +#endif // WITH_WSREP clean_up(!opt_abort && (exit_code || !opt_bootstrap)); /* purecov: inspected */ DBUG_PRINT("quit",("done with cleanup in unireg_abort")); mysqld_exit(exit_code); @@ -2092,6 +2203,19 @@ static void clean_up_mutexes() mysql_cond_destroy(&COND_thread_count); mysql_cond_destroy(&COND_thread_cache); mysql_cond_destroy(&COND_flush_thread_cache); +#ifdef WITH_WSREP + (void) mysql_mutex_destroy(&LOCK_wsrep_ready); + (void) mysql_cond_destroy(&COND_wsrep_ready); + (void) mysql_mutex_destroy(&LOCK_wsrep_sst); + (void) mysql_cond_destroy(&COND_wsrep_sst); + (void) mysql_mutex_destroy(&LOCK_wsrep_sst_init); + (void) mysql_cond_destroy(&COND_wsrep_sst_init); + (void) mysql_mutex_destroy(&LOCK_wsrep_rollback); + (void) mysql_cond_destroy(&COND_wsrep_rollback); + (void) mysql_mutex_destroy(&LOCK_wsrep_replaying); + (void) mysql_cond_destroy(&COND_wsrep_replaying); + (void) mysql_mutex_destroy(&LOCK_wsrep_slave_threads); +#endif mysql_mutex_destroy(&LOCK_server_started); mysql_cond_destroy(&COND_server_started); mysql_mutex_destroy(&LOCK_prepare_ordered); @@ -2406,6 +2530,10 @@ static MYSQL_SOCKET activate_tcp_port(uint port) socket_errno); unireg_abort(1); } +#if defined(WITH_WSREP) && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) + (void) fcntl(mysql_socket_getfd(ip_sock), F_SETFD, FD_CLOEXEC); +#endif /* WITH_WSREP */ + DBUG_RETURN(ip_sock); } @@ -2532,6 +2660,9 @@ static void network_init(void) if (mysql_socket_listen(unix_sock,(int) back_log) < 0) sql_print_warning("listen() on Unix socket failed with error %d", socket_errno); +#if defined(WITH_WSREP) && defined(HAVE_FCNTL) + (void) fcntl(mysql_socket_getfd(unix_sock), F_SETFD, FD_CLOEXEC); +#endif /* WITH_WSREP */ } #endif DBUG_PRINT("info",("server started")); @@ -2548,7 +2679,11 @@ static void network_init(void) @note For the connection that is doing shutdown, this is called twice */ +#ifdef WITH_WSREP +void close_connection(THD *thd, uint sql_errno, bool lock) +#else void close_connection(THD *thd, uint sql_errno) +#endif { DBUG_ENTER("close_connection"); @@ -3835,7 +3970,13 @@ static int init_common_variables() } else opt_log_basename= glob_hostname; - +#ifdef WITH_WSREP + if (0 == wsrep_node_name || 0 == wsrep_node_name[0]) + { + my_free((void *)wsrep_node_name); + wsrep_node_name= my_strdup(glob_hostname, MYF(MY_WME)); + } +#endif /* WITH_WSREP */ if (!*pidfile_name) { strmake(pidfile_name, opt_log_basename, sizeof(pidfile_name)-5); @@ -3894,7 +4035,11 @@ static int init_common_variables() compile_time_assert(sizeof(com_status_vars)/sizeof(com_status_vars[0]) - 1 == SQLCOM_END + 8); #endif - +#ifdef WITH_WSREP + /* This is a protection against mutually incompatible option values. */ + if (WSREP_ON && wsrep_check_opts (remaining_argc, remaining_argv)) + global_system_variables.wsrep_on= 0; +#endif /* WITH_WSREP */ if (get_options(&remaining_argc, &remaining_argv)) return 1; set_server_version(); @@ -4534,10 +4679,18 @@ static int init_server_components() /* need to configure logging before initializing storage engines */ if (!opt_bin_log_used) { +#ifdef WITH_WSREP + if (!WSREP_ON && opt_log_slave_updates) +#else if (opt_log_slave_updates) +#endif sql_print_warning("You need to use --log-bin to make " "--log-slave-updates work."); +#ifdef WITH_WSREP + if (!WSREP_ON && binlog_format_used) +#else if (binlog_format_used) +#endif sql_print_warning("You need to use --log-bin to make " "--binlog-format work."); } @@ -4563,6 +4716,39 @@ will be ignored as the --log-bin option is not defined."); } #endif +#ifdef WITH_WSREP /* WSREP BEFORE SE */ + if (!wsrep_recovery) + { + if (opt_bootstrap) // bootsrap option given - disable wsrep functionality + { + wsrep_provider_init(WSREP_NONE); + if (wsrep_init()) unireg_abort(1); + } + else // full wsrep initialization + { + // add basedir/bin to PATH to resolve wsrep script names + char* const tmp_path((char*)alloca(strlen(mysql_home) + + strlen("/bin") + 1)); + if (tmp_path) + { + strcpy(tmp_path, mysql_home); + strcat(tmp_path, "/bin"); + wsrep_prepend_PATH(tmp_path); + } + else + { + WSREP_ERROR("Could not append %s/bin to PATH", mysql_home); + } + + if (wsrep_before_SE()) + { + set_ports(); // this is also called in network_init() later but we need + // to know mysqld_port now - lp:1071882 + wsrep_init_startup(true); + } + } + } +#endif /* WITH_WSREP */ if (opt_bin_log) { /* Reports an error and aborts, if the --log-bin's path @@ -4768,10 +4954,29 @@ a file name for --log-bin-index option", opt_binlog_index_name); internal_tmp_table_max_key_segments= myisam_max_key_segments(); #endif +#ifdef WITH_WSREP + if (!opt_bin_log) + { + wsrep_emulate_bin_log= 1; + } +#endif tc_log= (total_ha_2pc > 1 ? (opt_bin_log ? (TC_LOG *) &mysql_bin_log : +#ifdef WITH_WSREP + (WSREP_ON ? + (TC_LOG *) &tc_log_dummy : + (TC_LOG *) &tc_log_mmap)) : +#else (TC_LOG *) &tc_log_mmap) : +#endif (TC_LOG *) &tc_log_dummy); +#ifdef WITH_WSREP + WSREP_DEBUG("Initial TC log open: %s", + (tc_log == &mysql_bin_log) ? "binlog" : + (tc_log == &tc_log_mmap) ? "mmap" : + (tc_log == &tc_log_dummy) ? "dummy" : "unknown" + ); +#endif if (tc_log->open(opt_bin_log ? opt_bin_logname : opt_tc_log_file)) { @@ -5286,8 +5491,33 @@ int mysqld_main(int argc, char **argv) if (Events::init(opt_noacl || opt_bootstrap)) unireg_abort(1); +#ifdef WITH_WSREP /* WSREP AFTER SE */ if (opt_bootstrap) { + /*! bootstrap wsrep init was taken care of above */ + } + else + { + wsrep_SE_initialized(); + + if (wsrep_before_SE()) + { + /*! in case of no SST wsrep waits in view handler callback */ + wsrep_SE_init_grab(); + wsrep_SE_init_done(); + /*! in case of SST wsrep waits for wsrep->sst_received */ + wsrep_sst_continue(); + } + else + { + wsrep_init_startup (false); + } + + wsrep_create_appliers(wsrep_slave_threads - 1); + } +#endif /* WITH_WSREP */ + if (opt_bootstrap) + { select_thread_in_use= 0; // Allow 'kill' to work bootstrap(mysql_stdin); if (!kill_in_progress) @@ -5354,6 +5584,9 @@ int mysqld_main(int argc, char **argv) #ifdef EXTRA_DEBUG2 sql_print_error("Before Lock_thread_count"); #endif +#ifdef WITH_WSREP + WSREP_DEBUG("Before Lock_thread_count"); +#endif mysql_mutex_lock(&LOCK_thread_count); DBUG_PRINT("quit", ("Got thread_count mutex")); select_thread_in_use=0; // For close_connections @@ -5619,6 +5852,9 @@ static void bootstrap(MYSQL_FILE *file) DBUG_ENTER("bootstrap"); THD *thd= new THD; +#ifdef WITH_WSREP + thd->variables.wsrep_on= 0; +#endif thd->bootstrap=1; my_net_init(&thd->net,(st_vio*) 0, MYF(0)); thd->max_client_packet_length= thd->net.max_packet; @@ -5755,7 +5991,11 @@ void create_thread_to_handle_connection(THD *thd) my_snprintf(error_message_buff, sizeof(error_message_buff), ER_THD(thd, ER_CANT_CREATE_THREAD), error); net_send_error(thd, ER_CANT_CREATE_THREAD, error_message_buff, NULL); +#ifdef WITH_WSREP + close_connection(thd, ER_OUT_OF_RESOURCES ,0); +#else close_connection(thd, ER_OUT_OF_RESOURCES); +#endif /* WITH_WSREP */ mysql_mutex_lock(&LOCK_thread_count); thd->unlink(); @@ -5801,7 +6041,11 @@ static void create_new_thread(THD *thd) mysql_mutex_unlock(&LOCK_connection_count); DBUG_PRINT("error",("Too many connections")); +#ifdef WITH_WSREP + close_connection(thd, ER_CON_COUNT_ERROR, 1); +#else close_connection(thd, ER_CON_COUNT_ERROR); +#endif /* WITH_WSREP */ statistic_increment(denied_connections, &LOCK_status); delete thd; DBUG_VOID_RETURN; @@ -6003,6 +6247,9 @@ void handle_connections_sockets() sleep(1); // Give other threads some time continue; } +#if defined(WITH_WSREP) && defined(HAVE_FCNTL) && defined(FD_CLOEXEC) + (void) fcntl(mysql_socket_getfd(new_sock), F_SETFD, FD_CLOEXEC); +#endif /* WITH_WSREP */ #ifdef HAVE_LIBWRAP { @@ -6189,7 +6436,11 @@ pthread_handler_t handle_connections_namedpipes(void *arg) if (!(thd->net.vio= vio_new_win32pipe(hConnectedPipe)) || my_net_init(&thd->net, thd->net.vio, MYF(MY_THREAD_SPECIFIC))) { +#ifdef WITH_WSREP + close_connection(thd, ER_OUT_OF_RESOURCES, 1); +#else close_connection(thd, ER_OUT_OF_RESOURCES); +#endif delete thd; set_current_thd(0); continue; @@ -6387,7 +6638,11 @@ pthread_handler_t handle_connections_shared_memory(void *arg) event_conn_closed)) || my_net_init(&thd->net, thd->net.vio, MYF(MY_THREAD_SPECIFIC))) { +#ifdef WITH_WSREP + close_connection(thd, ER_OUT_OF_RESOURCES, 1); +#else close_connection(thd, ER_OUT_OF_RESOURCES); +#endif errmsg= 0; goto errorconn; } @@ -7615,6 +7870,19 @@ SHOW_VAR status_vars[]= { #ifdef ENABLED_PROFILING {"Uptime_since_flush_status",(char*) &show_flushstatustime, SHOW_SIMPLE_FUNC}, #endif +#ifdef WITH_WSREP + {"wsrep_connected", (char*) &wsrep_connected, SHOW_BOOL}, + {"wsrep_ready", (char*) &wsrep_ready, SHOW_BOOL}, + {"wsrep_cluster_state_uuid", (char*) &wsrep_cluster_state_uuid,SHOW_CHAR_PTR}, + {"wsrep_cluster_conf_id", (char*) &wsrep_cluster_conf_id, SHOW_LONGLONG}, + {"wsrep_cluster_status", (char*) &wsrep_cluster_status, SHOW_CHAR_PTR}, + {"wsrep_cluster_size", (char*) &wsrep_cluster_size, SHOW_LONG}, + {"wsrep_local_index", (char*) &wsrep_local_index, SHOW_LONG}, + {"wsrep_provider_name", (char*) &wsrep_provider_name, SHOW_CHAR_PTR}, + {"wsrep_provider_version", (char*) &wsrep_provider_version, SHOW_CHAR_PTR}, + {"wsrep_provider_vendor", (char*) &wsrep_provider_vendor, SHOW_CHAR_PTR}, + {"wsrep", (char*) &wsrep_show_status, SHOW_FUNC}, +#endif {NullS, NullS, SHOW_LONG} }; @@ -7952,6 +8220,10 @@ static int mysql_init_variables(void) tmpenv = DEFAULT_MYSQL_HOME; (void) strmake(mysql_home, tmpenv, sizeof(mysql_home)-1); #endif +#ifdef WITH_WSREP + if (WSREP_ON && wsrep_init_vars()) + return 1; +#endif return 0; } @@ -8208,6 +8480,14 @@ mysqld_get_one_option(int optid, case OPT_LOWER_CASE_TABLE_NAMES: lower_case_table_names_used= 1; break; +#ifdef WITH_WSREP + case OPT_WSREP_START_POSITION: + wsrep_start_position_init (argument); + break; + case OPT_WSREP_SST_AUTH: + wsrep_sst_auth_init (argument); + break; +#endif #if defined(ENABLED_DEBUG_SYNC) case OPT_DEBUG_SYNC_TIMEOUT: /* @@ -8336,6 +8616,25 @@ mysqld_get_one_option(int optid, #endif break; } +#ifdef WITH_WSREP + mysql_mutex_init(key_LOCK_wsrep_ready, + &LOCK_wsrep_ready, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_wsrep_ready, &COND_wsrep_ready, NULL); + mysql_mutex_init(key_LOCK_wsrep_sst, + &LOCK_wsrep_sst, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_wsrep_sst, &COND_wsrep_sst, NULL); + mysql_mutex_init(key_LOCK_wsrep_sst_init, + &LOCK_wsrep_sst_init, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_wsrep_sst_init, &COND_wsrep_sst_init, NULL); + mysql_mutex_init(key_LOCK_wsrep_rollback, + &LOCK_wsrep_rollback, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_wsrep_rollback, &COND_wsrep_rollback, NULL); + mysql_mutex_init(key_LOCK_wsrep_replaying, + &LOCK_wsrep_replaying, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_wsrep_replaying, &COND_wsrep_replaying, NULL); + mysql_mutex_init(key_LOCK_wsrep_slave_threads, + &LOCK_wsrep_slave_threads, MY_MUTEX_INIT_FAST); +#endif return 0; } @@ -8894,8 +9193,6 @@ static int test_if_case_insensitive(const char *dir_name) DBUG_PRINT("exit", ("result: %d", result)); DBUG_RETURN(result); } - - #ifndef EMBEDDED_LIBRARY /** @@ -8924,6 +9221,487 @@ static void create_pid_file() } #endif /* EMBEDDED_LIBRARY */ +#ifdef WITH_WSREP +typedef void (*wsrep_thd_processor_fun)(THD *); + +pthread_handler_t start_wsrep_THD(void *arg) +{ + THD *thd; + wsrep_thd_processor_fun processor= (wsrep_thd_processor_fun)arg; + + if (my_thread_init()) + { + WSREP_ERROR("Could not initialize thread"); + return(NULL); + } + + if (!(thd= new THD(true))) + { + return(NULL); + } + mysql_mutex_lock(&LOCK_thread_count); + thd->thread_id=thread_id++; + + thd->real_id=pthread_self(); // Keep purify happy + thread_count++; + thread_created++; + threads.append(thd); + + my_net_init(&thd->net,(st_vio*) 0, MYF(0)); + + DBUG_PRINT("wsrep",(("creating thread %lld"), (long long)thd->thread_id)); + thd->prior_thr_create_utime= thd->start_utime= microsecond_interval_timer(); + (void) mysql_mutex_unlock(&LOCK_thread_count); + + /* from bootstrap()... */ + thd->bootstrap=1; + thd->max_client_packet_length= thd->net.max_packet; + thd->security_ctx->master_access= ~(ulong)0; + + /* from handle_one_connection... */ + pthread_detach_this_thread(); + + mysql_thread_set_psi_id(thd->thread_id); + thd->thr_create_utime= microsecond_interval_timer(); + if (MYSQL_CALLBACK_ELSE(thread_scheduler, init_new_connection_thread, (), 0)) + { + close_connection(thd, ER_OUT_OF_RESOURCES, 1); + statistic_increment(aborted_connects,&LOCK_status); + MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); + + return(NULL); + } + +// </5.1.17> + /* + handle_one_connection() is normally the only way a thread would + start and would always be on the very high end of the stack , + therefore, the thread stack always starts at the address of the + first local variable of handle_one_connection, which is thd. We + need to know the start of the stack so that we could check for + stack overruns. + */ + DBUG_PRINT("wsrep", ("handle_one_connection called by thread %lld\n", + (long long)thd->thread_id)); + /* now that we've called my_thread_init(), it is safe to call DBUG_* */ + + thd->thread_stack= (char*) &thd; + if (thd->store_globals()) + { + close_connection(thd, ER_OUT_OF_RESOURCES, 1); + statistic_increment(aborted_connects,&LOCK_status); + MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 0)); + delete thd; + + return(NULL); + } + + thd->system_thread= SYSTEM_THREAD_SLAVE_SQL; + thd->security_ctx->skip_grants(); + + /* handle_one_connection() again... */ + //thd->version= refresh_version; + thd->proc_info= 0; + thd->set_command(COM_SLEEP); + thd->set_time(); + thd->init_for_queries(); + + mysql_mutex_lock(&LOCK_connection_count); + ++connection_count; + mysql_mutex_unlock(&LOCK_connection_count); + + mysql_mutex_lock(&LOCK_thread_count); + wsrep_running_threads++; + mysql_cond_signal(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); + + processor(thd); + + close_connection(thd, 0, 1); + + mysql_mutex_lock(&LOCK_thread_count); + wsrep_running_threads--; + mysql_cond_signal(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); + + // Note: We can't call THD destructor without crashing + // if plugins have not been initialized. However, in most of the + // cases this means that pre SE initialization SST failed and + // we are going to exit anyway. + if (plugins_are_initialized) + { + net_end(&thd->net); + MYSQL_CALLBACK(thread_scheduler, end_thread, (thd, 1)); + } + else + { + // TODO: lightweight cleanup to get rid of: + // 'Error in my_thread_global_end(): 2 threads didn't exit' + // at server shutdown + } + + if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION) + { + mysql_mutex_lock(&LOCK_thread_count); + delete thd; + thread_count--; + mysql_mutex_unlock(&LOCK_thread_count); + } + return(NULL); +} + +void wsrep_create_rollbacker() +{ + if (wsrep_provider && strcasecmp(wsrep_provider, "none")) + { + pthread_t hThread; + /* create rollbacker */ + if (pthread_create( &hThread, &connection_attrib, + start_wsrep_THD, (void*)wsrep_rollback_process)) + WSREP_WARN("Can't create thread to manage wsrep rollback"); + } +} + +void wsrep_create_appliers(long threads) +{ + if (!wsrep_connected) + { + /* see wsrep_replication_start() for the logic */ + if (wsrep_cluster_address && strlen(wsrep_cluster_address) && + wsrep_provider && strcasecmp(wsrep_provider, "none")) + { + WSREP_ERROR("Trying to launch slave threads before creating " + "connection at '%s'", wsrep_cluster_address); + assert(0); + } + return; + } + + long wsrep_threads=0; + pthread_t hThread; + while (wsrep_threads++ < threads) { + if (pthread_create( + &hThread, &connection_attrib, + start_wsrep_THD, (void*)wsrep_replication_process)) + WSREP_WARN("Can't create thread to manage wsrep replication"); + } +} +/**/ +static bool abort_replicated(THD *thd) +{ + bool ret_code= false; + if (thd->wsrep_query_state== QUERY_COMMITTING) + { + if (wsrep_debug) WSREP_INFO("aborting replicated trx: %lu", thd->real_id); + + (void)wsrep_abort_thd(thd, thd, TRUE); + ret_code= true; + } + return ret_code; +} +/**/ +static inline bool is_client_connection(THD *thd) +{ + return (thd->wsrep_client_thread && thd->variables.wsrep_on); +} + +static inline bool is_replaying_connection(THD *thd) +{ + bool ret; + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + ret= (thd->wsrep_conflict_state == REPLAYING) ? true : false; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + return ret; +} + +static inline bool is_committing_connection(THD *thd) +{ + bool ret; + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + ret= (thd->wsrep_query_state == QUERY_COMMITTING) ? true : false; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + return ret; +} + +static bool have_client_connections() +{ + THD *tmp; + + I_List_iterator<THD> it(threads); + while ((tmp=it++)) + { + DBUG_PRINT("quit",("Informing thread %ld that it's time to die", + tmp->thread_id)); + if (is_client_connection(tmp) && tmp->killed == KILL_CONNECTION) + { + (void)abort_replicated(tmp); + return true; + } + } + return false; +} + +/* + returns the number of wsrep appliers running. + However, the caller (thd parameter) is not taken in account + */ +static int have_wsrep_appliers(THD *thd) +{ + int ret= 0; + THD *tmp; + + I_List_iterator<THD> it(threads); + while ((tmp=it++)) + { + ret+= (tmp != thd && tmp->wsrep_applier); + } + return ret; +} + +static void wsrep_close_thread(THD *thd) +{ + thd->killed= KILL_CONNECTION; + MYSQL_CALLBACK(thread_scheduler, post_kill_notification, (thd)); + if (thd->mysys_var) + { + thd->mysys_var->abort=1; + mysql_mutex_lock(&thd->mysys_var->mutex); + if (thd->mysys_var->current_cond) + { + mysql_mutex_lock(thd->mysys_var->current_mutex); + mysql_cond_broadcast(thd->mysys_var->current_cond); + mysql_mutex_unlock(thd->mysys_var->current_mutex); + } + mysql_mutex_unlock(&thd->mysys_var->mutex); + } +} + +static my_bool have_committing_connections() +{ + THD *tmp; + mysql_mutex_lock(&LOCK_thread_count); // For unlink from list + + I_List_iterator<THD> it(threads); + while ((tmp=it++)) + { + if (!is_client_connection(tmp)) + continue; + + if (is_committing_connection(tmp)) + { + mysql_mutex_unlock(&LOCK_thread_count); + return TRUE; + } + } + mysql_mutex_unlock(&LOCK_thread_count); + return FALSE; +} + +int wsrep_wait_committing_connections_close(int wait_time) +{ + int sleep_time= 100; + + while (have_committing_connections() && wait_time > 0) + { + WSREP_DEBUG("wait for committing transaction to close: %d", wait_time); + my_sleep(sleep_time); + wait_time -= sleep_time; + } + if (have_committing_connections()) + { + return 1; + } + return 0; +} + +void wsrep_close_client_connections(my_bool wait_to_end) +{ + /* + First signal all threads that it's time to die + */ + + THD *tmp; + mysql_mutex_lock(&LOCK_thread_count); // For unlink from list + + bool kill_cached_threads_saved= kill_cached_threads; + kill_cached_threads= true; // prevent future threads caching + mysql_cond_broadcast(&COND_thread_cache); // tell cached threads to die + + I_List_iterator<THD> it(threads); + while ((tmp=it++)) + { + DBUG_PRINT("quit",("Informing thread %ld that it's time to die", + tmp->thread_id)); + /* We skip slave threads & scheduler on this first loop through. */ + if (!is_client_connection(tmp)) + continue; + + if (is_replaying_connection(tmp)) + { + tmp->killed= KILL_CONNECTION; + continue; + } + + /* replicated transactions must be skipped */ + if (abort_replicated(tmp)) + continue; + + WSREP_DEBUG("closing connection %ld", tmp->thread_id); + wsrep_close_thread(tmp); + } + mysql_mutex_unlock(&LOCK_thread_count); + + if (thread_count) + sleep(2); // Give threads time to die + + mysql_mutex_lock(&LOCK_thread_count); + /* + Force remaining threads to die by closing the connection to the client + */ + + I_List_iterator<THD> it2(threads); + while ((tmp=it2++)) + { +#ifndef __bsdi__ // Bug in BSDI kernel + if (is_client_connection(tmp) && + !abort_replicated(tmp) && + !is_replaying_connection(tmp)) + { + WSREP_INFO("killing local connection: %ld",tmp->thread_id); + close_connection(tmp,0,0); + } +#endif + } + + DBUG_PRINT("quit",("Waiting for threads to die (count=%u)",thread_count)); + if (wsrep_debug) + WSREP_INFO("waiting for client connections to close: %u", thread_count); + + while (wait_to_end && have_client_connections()) + { + mysql_cond_wait(&COND_thread_count, &LOCK_thread_count); + DBUG_PRINT("quit",("One thread died (count=%u)", thread_count)); + } + + kill_cached_threads= kill_cached_threads_saved; + + mysql_mutex_unlock(&LOCK_thread_count); + + /* All client connection threads have now been aborted */ +} + +void wsrep_close_applier(THD *thd) +{ + WSREP_DEBUG("closing applier %ld", thd->thread_id); + wsrep_close_thread(thd); +} + +static void wsrep_close_threads(THD *thd) +{ + THD *tmp; + mysql_mutex_lock(&LOCK_thread_count); // For unlink from list + + I_List_iterator<THD> it(threads); + while ((tmp=it++)) + { + DBUG_PRINT("quit",("Informing thread %ld that it's time to die", + tmp->thread_id)); + /* We skip slave threads & scheduler on this first loop through. */ + if (tmp->wsrep_applier && tmp != thd) + { + WSREP_DEBUG("closing wsrep thread %ld", tmp->thread_id); + wsrep_close_thread (tmp); + } + } + + mysql_mutex_unlock(&LOCK_thread_count); +} + +void wsrep_close_applier_threads(int count) +{ + THD *tmp; + mysql_mutex_lock(&LOCK_thread_count); // For unlink from list + + I_List_iterator<THD> it(threads); + while ((tmp=it++) && count) + { + DBUG_PRINT("quit",("Informing thread %ld that it's time to die", + tmp->thread_id)); + /* We skip slave threads & scheduler on this first loop through. */ + if (tmp->wsrep_applier) + { + WSREP_DEBUG("closing wsrep applier thread %ld", tmp->thread_id); + tmp->wsrep_applier_closing= TRUE; + count--; + } + } + + mysql_mutex_unlock(&LOCK_thread_count); +} + +void wsrep_wait_appliers_close(THD *thd) +{ + /* Wait for wsrep appliers to gracefully exit */ + mysql_mutex_lock(&LOCK_thread_count); + while (have_wsrep_appliers(thd) > 1) + // 1 is for rollbacker thread which needs to be killed explicitly. + // This gotta be fixed in a more elegant manner if we gonna have arbitrary + // number of non-applier wsrep threads. + { + if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION) + { + mysql_mutex_unlock(&LOCK_thread_count); + my_sleep(100); + mysql_mutex_lock(&LOCK_thread_count); + } + else + mysql_cond_wait(&COND_thread_count,&LOCK_thread_count); + DBUG_PRINT("quit",("One applier died (count=%u)",thread_count)); + } + mysql_mutex_unlock(&LOCK_thread_count); + /* Now kill remaining wsrep threads: rollbacker */ + wsrep_close_threads (thd); + /* and wait for them to die */ + mysql_mutex_lock(&LOCK_thread_count); + while (have_wsrep_appliers(thd) > 0) + { + if (thread_handling > SCHEDULER_ONE_THREAD_PER_CONNECTION) + { + mysql_mutex_unlock(&LOCK_thread_count); + my_sleep(100); + mysql_mutex_lock(&LOCK_thread_count); + } + else + mysql_cond_wait(&COND_thread_count,&LOCK_thread_count); + DBUG_PRINT("quit",("One thread died (count=%u)",thread_count)); + } + mysql_mutex_unlock(&LOCK_thread_count); + + /* All wsrep applier threads have now been aborted. However, if this thread + is also applier, we are still running... + */ +} + +void wsrep_kill_mysql(THD *thd) +{ + if (mysqld_server_started) + { + if (!shutdown_in_progress) + { + WSREP_INFO("starting shutdown"); + kill_mysql(); + } + } + else + { + unireg_abort(1); + } +} +#endif /* WITH_WSREP */ /** Remove the process' pid file. @@ -9268,6 +10046,14 @@ void init_server_psi_keys(void) count= array_elements(com_statement_info); mysql_statement_register(category, com_statement_info, count); +#ifdef WITH_WSREP /* WSREP AFTER SE */ + if (wsrep_recovery) + { + select_thread_in_use= 0; + wsrep_recover(); + unireg_abort(0); + } +#endif /* WITH_WSREP */ /* When a new packet is received, it is instrumented as "statement/com/". diff --git a/sql/mysqld.h b/sql/mysqld.h index e07b5d5c41c..55a631c3ccf 100644 --- a/sql/mysqld.h +++ b/sql/mysqld.h @@ -54,7 +54,11 @@ typedef Bitmap<((MAX_INDEXES+7)/8*8)> key_map; /* Used for finding keys */ some places */ /* Function prototypes */ void kill_mysql(void); +#ifdef WITH_WSREP +void close_connection(THD *thd, uint sql_errno= 0, bool lock=1); +#else void close_connection(THD *thd, uint sql_errno= 0); +#endif void handle_connection_in_main_thread(THD *thd); void create_thread_to_handle_connection(THD *thd); void delete_running_thd(THD *thd); @@ -225,6 +229,10 @@ extern pthread_key(MEM_ROOT**,THR_MALLOC); extern PSI_mutex_key key_PAGE_lock, key_LOCK_sync, key_LOCK_active, key_LOCK_pool, key_LOCK_pending_checkpoint; #endif /* HAVE_MMAP */ +#ifdef WITH_WSREP +extern PSI_mutex_key key_LOCK_wsrep_thd; +extern PSI_cond_key key_COND_wsrep_thd; +#endif /* HAVE_MMAP */ #ifdef HAVE_OPENSSL extern PSI_mutex_key key_LOCK_des_key_file; @@ -557,6 +565,14 @@ enum options_mysqld OPT_SSL_KEY, OPT_UPDATE_LOG, OPT_WANT_CORE, +#ifdef WITH_WSREP + OPT_WSREP_PROVIDER, + OPT_WSREP_PROVIDER_OPTIONS, + OPT_WSREP_CLUSTER_ADDRESS, + OPT_WSREP_START_POSITION, + OPT_WSREP_SST_AUTH, + OPT_WSREP_RECOVER, +#endif OPT_which_is_always_the_last }; #endif @@ -700,4 +716,5 @@ extern uint internal_tmp_table_max_key_segments; extern uint volatile global_disable_checkpoint; extern my_bool opt_help; + #endif /* MYSQLD_INCLUDED */ diff --git a/sql/protocol.cc b/sql/protocol.cc index f6e9e9e62e1..a86da94af61 100644 --- a/sql/protocol.cc +++ b/sql/protocol.cc @@ -485,6 +485,14 @@ static uchar *net_store_length_fast(uchar *packet, uint length) void Protocol::end_statement() { +#ifdef WITH_WSREP + /*sanity check, can be removed before 1.0 release */ + if (WSREP(thd) && thd->wsrep_conflict_state== REPLAYING) + { + WSREP_ERROR("attempting net_end_statement while replaying"); + return; + } +#endif DBUG_ENTER("Protocol::end_statement"); DBUG_ASSERT(! thd->stmt_da->is_sent); bool error= FALSE; diff --git a/sql/set_var.h b/sql/set_var.h index 6cb0cd33f87..52964a1f29d 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -240,6 +240,9 @@ public: int check(THD *thd); int update(THD *thd); int light_check(THD *thd); +#ifdef WITH_WSREP + int wsrep_store_variable(THD *thd); +#endif }; @@ -321,6 +324,9 @@ extern sys_var *Sys_autocommit_ptr; CHARSET_INFO *get_old_charset_by_name(const char *old_name); +#ifdef WITH_WSREP +int sql_set_wsrep_variables(THD *thd, List<set_var_base> *var_list); +#endif int sys_var_init(); int sys_var_add_options(DYNAMIC_ARRAY *long_options, int parse_flags); void sys_var_end(void); diff --git a/sql/slave.cc b/sql/slave.cc index c7f4dc08096..327f1b763a3 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -53,6 +53,9 @@ // Create_file_log_event, // Format_description_log_event +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif #ifdef HAVE_REPLICATION #include "rpl_tblmap.h" @@ -3026,6 +3029,23 @@ int apply_event_and_update_pos(Log_event* ev, THD* thd, Relay_log_info* rli) ev->thd = thd; // because up to this point, ev->thd == 0 int reason= ev->shall_skip(rli); +#ifdef WITH_WSREP + if (WSREP_ON && (ev->get_type_code() == XID_EVENT || + (ev->get_type_code() == QUERY_EVENT && thd->wsrep_mysql_replicated > 0 && + (!strncasecmp(((Query_log_event*)ev)->query , "BEGIN", 5) || + !strncasecmp(((Query_log_event*)ev)->query , "COMMIT", 6) )))) + { + if (++thd->wsrep_mysql_replicated < (int)wsrep_mysql_replication_bundle) + { + WSREP_DEBUG("skipping wsrep commit %d", thd->wsrep_mysql_replicated); + reason = Log_event::EVENT_SKIP_IGNORE; + } + else + { + thd->wsrep_mysql_replicated = 0; + } + } +#endif if (reason == Log_event::EVENT_SKIP_COUNT) { DBUG_ASSERT(rli->slave_skip_counter > 0); @@ -4004,6 +4024,11 @@ pthread_handler_t handle_slave_sql(void *arg) #endif DBUG_ASSERT(rli->sql_thd == thd); +#ifdef WITH_WSREP + thd->wsrep_exec_mode= LOCAL_STATE; + /* synchronize with wsrep replication */ + if (WSREP_ON) wsrep_ready_wait(); +#endif DBUG_PRINT("master_info",("log_file_name: %s position: %s", rli->group_master_log_name, llstr(rli->group_master_log_pos,llbuff))); diff --git a/sql/sp.cc b/sql/sp.cc index 41a1ae583fc..b60411a9121 100644 --- a/sql/sp.cc +++ b/sql/sp.cc @@ -2254,3 +2254,37 @@ sp_load_for_information_schema(THD *thd, TABLE *proc_table, String *db, thd->lex= old_lex; return sp; } +#ifdef WITH_WSREP +int wsrep_create_sp(THD *thd, uchar** buf, uint* buf_len) +{ + String log_query; + sp_head *sp = thd->lex->sphead; + ulong saved_mode= thd->variables.sql_mode; + String retstr(64); + retstr.set_charset(system_charset_info); + + log_query.set_charset(system_charset_info); + + if (sp->m_type == TYPE_ENUM_FUNCTION) + { + sp_returns_type(thd, retstr, sp); + } + + if (!create_string(thd, &log_query, + sp->m_type, + (sp->m_explicit_name ? sp->m_db.str : NULL), + (sp->m_explicit_name ? sp->m_db.length : 0), + sp->m_name.str, sp->m_name.length, + sp->m_params.str, sp->m_params.length, + retstr.c_ptr(), retstr.length(), + sp->m_body.str, sp->m_body.length, + sp->m_chistics, &(thd->lex->definer->user), + &(thd->lex->definer->host), + saved_mode)) + { + WSREP_WARN("SP create string failed: %s", thd->query()); + return 1; + } + return wsrep_to_buf_helper(thd, log_query.ptr(), log_query.length(), buf, buf_len); +} +#endif /* WITH_WSREP */ diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index e776968792c..d056727c2fd 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -1862,6 +1862,9 @@ int check_change_password(THD *thd, const char *host, const char *user, return(1); } if (!thd->slave_thread && +#ifdef WITH_WSREP + (!WSREP(thd) || !thd->wsrep_applier) && +#endif /* WITH_WSREP */ (strcmp(thd->security_ctx->user, user) || my_strcasecmp(system_charset_info, host, thd->security_ctx->priv_host))) @@ -1869,7 +1872,12 @@ int check_change_password(THD *thd, const char *host, const char *user, if (check_access(thd, UPDATE_ACL, "mysql", NULL, NULL, 1, 0)) return(1); } +#ifdef WITH_WSREP + if ((!WSREP(thd) || !thd->wsrep_applier) && + !thd->slave_thread && !thd->security_ctx->user[0]) +#else if (!thd->slave_thread && !thd->security_ctx->user[0]) +#endif /* WITH_WSREP */ { my_message(ER_PASSWORD_ANONYMOUS_USER, ER(ER_PASSWORD_ANONYMOUS_USER), MYF(0)); @@ -1913,6 +1921,9 @@ bool change_password(THD *thd, const char *host, const char *user, enum_binlog_format save_binlog_format; uint new_password_len= (uint) strlen(new_password); bool result= 1; +#ifdef WITH_WSREP + const CSET_STRING query_save = thd->query_string; +#endif /* WITH_WSREP */ DBUG_ENTER("change_password"); DBUG_PRINT("enter",("host: '%s' user: '%s' new_password: '%s'", host,user,new_password)); @@ -1920,6 +1931,18 @@ bool change_password(THD *thd, const char *host, const char *user, if (check_change_password(thd, host, user, new_password, new_password_len)) DBUG_RETURN(1); +#ifdef WITH_WSREP + if (WSREP(thd) && !thd->wsrep_applier) + { + query_length= sprintf(buff, "SET PASSWORD FOR '%-.120s'@'%-.120s'='%-.120s'", + user ? user : "", + host ? host : "", + new_password); + thd->set_query_inner(buff, query_length, system_charset_info); + + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, (char*)"user", NULL); + } +#endif /* WITH_WSREP */ tables.init_one_table("mysql", 5, "user", 4, "user", TL_WRITE); @@ -1999,9 +2022,23 @@ bool change_password(THD *thd, const char *host, const char *user, } end: close_mysql_tables(thd); +#ifdef WITH_WSREP + if (WSREP(thd) && !thd->wsrep_applier) + { + WSREP_TO_ISOLATION_END; + + thd->query_string = query_save; + thd->wsrep_exec_mode = LOCAL_STATE; + } +#endif /* WITH_WSREP */ thd->restore_stmt_binlog_format(save_binlog_format); DBUG_RETURN(result); +#ifdef WITH_WSREP + error: + WSREP_ERROR("Replication of SET PASSWORD failed: %s", buff); + DBUG_RETURN(result); +#endif /* WITH_WSREP */ } diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 9e3ea46f526..a9b7624af3c 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -1153,6 +1153,8 @@ bool Optimize_table_statement::execute(THD *thd) FALSE, UINT_MAX, FALSE)) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; + + WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL) res= (specialflag & (SPECIAL_SAFE_MODE | SPECIAL_NO_NEW_FUNC)) ? mysql_recreate_table(thd, first_table) : mysql_admin_table(thd, first_table, &m_lex->check_opt, @@ -1184,6 +1186,7 @@ bool Repair_table_statement::execute(THD *thd) FALSE, UINT_MAX, FALSE)) goto error; /* purecov: inspected */ thd->enable_slow_log= opt_log_slow_admin_statements; + WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL) res= mysql_admin_table(thd, first_table, &m_lex->check_opt, "repair", TL_WRITE, 1, test(m_lex->check_opt.sql_flags & TT_USEFRM), diff --git a/sql/sql_alter.cc b/sql/sql_alter.cc index c6c02773286..00691633aa8 100644 --- a/sql/sql_alter.cc +++ b/sql/sql_alter.cc @@ -17,7 +17,9 @@ #include "sql_table.h" // mysql_alter_table, // mysql_exchange_partition #include "sql_alter.h" - +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif /* WITH_WSREP */ bool Alter_table_statement::execute(THD *thd) { LEX *lex= thd->lex; @@ -97,6 +99,20 @@ bool Alter_table_statement::execute(THD *thd) thd->enable_slow_log= opt_log_slow_admin_statements; +#ifdef WITH_WSREP + TABLE *find_temporary_table(THD *thd, const TABLE_LIST *tl); + + if ((!thd->is_current_stmt_binlog_format_row() || + !find_temporary_table(thd, first_table)) && + wsrep_to_isolation_begin(thd, + lex->name.str ? select_lex->db : NULL, + lex->name.str ? lex->name.str : NULL, + first_table)) + { + WSREP_WARN("ALTER TABLE isolation failure"); + DBUG_RETURN(TRUE); + } +#endif /* WITH_WSREP */ result= mysql_alter_table(thd, select_lex->db, lex->name.str, &create_info, first_table, @@ -105,5 +121,7 @@ bool Alter_table_statement::execute(THD *thd) select_lex->order_list.first, lex->ignore, lex->online); +#ifdef WITH_WSREP +#endif /* WITH_WSREP */ DBUG_RETURN(result); } diff --git a/sql/sql_base.cc b/sql/sql_base.cc index b4c163f61ee..c9630aef126 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -61,6 +61,10 @@ #include <io.h> #endif +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" + +#endif // WITH_WSREP bool No_such_table_error_handler::handle_condition(THD *, @@ -4115,7 +4119,7 @@ thr_lock_type read_lock_type_for_table(THD *thd, */ bool log_on= mysql_bin_log.is_open() && thd->variables.sql_log_bin; ulong binlog_format= thd->variables.binlog_format; - if ((log_on == FALSE) || (binlog_format == BINLOG_FORMAT_ROW) || + if ((log_on == FALSE) || (WSREP_FORMAT(binlog_format) == BINLOG_FORMAT_ROW) || (table_list->table->s->table_category == TABLE_CATEGORY_LOG) || (table_list->table->s->table_category == TABLE_CATEGORY_PERFORMANCE) || !(is_update_query(prelocking_ctx->sql_command) || @@ -5066,6 +5070,22 @@ restart: } } } +#ifdef WITH_WSREP + if ((thd->lex->sql_command== SQLCOM_INSERT || + thd->lex->sql_command== SQLCOM_INSERT_SELECT || + thd->lex->sql_command== SQLCOM_REPLACE || + thd->lex->sql_command== SQLCOM_REPLACE_SELECT || + thd->lex->sql_command== SQLCOM_UPDATE || + thd->lex->sql_command== SQLCOM_UPDATE_MULTI || + thd->lex->sql_command== SQLCOM_LOAD || + thd->lex->sql_command== SQLCOM_DELETE) && + wsrep_replicate_myisam && + (*start)->table && (*start)->table->file->ht->db_type == DB_TYPE_MYISAM) + { + WSREP_TO_ISOLATION_BEGIN(NULL, NULL, (*start)); + } + error: +#endif err: free_root(&new_frm_mem, MYF(0)); // Free pre-alloced block @@ -5780,7 +5800,7 @@ bool lock_tables(THD *thd, TABLE_LIST *tables, uint count, We can solve these problems in mixed mode by switching to binlogging if at least one updated table is used by sub-statement */ - if (thd->variables.binlog_format != BINLOG_FORMAT_ROW && tables && + if (WSREP_FORMAT(thd->variables.binlog_format) != BINLOG_FORMAT_ROW && tables && has_write_table_with_auto_increment(thd->lex->first_not_own_table())) thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_AUTOINC_COLUMNS); } @@ -9253,7 +9273,19 @@ bool mysql_notify_thread_having_shared_lock(THD *thd, THD *in_use, (e.g. see partitioning code). */ if (!thd_table->needs_reopen()) +#ifdef WITH_WSREP + { + signalled|= mysql_lock_abort_for_thread(thd, thd_table); + if (thd && WSREP(thd) && wsrep_thd_is_brute_force((void *)thd)) + { + WSREP_DEBUG("remove_table_from_cache: %llu", + (unsigned long long) thd->real_id); + wsrep_abort_thd((void *)thd, (void *)in_use, FALSE); + } + } +#else signalled|= mysql_lock_abort_for_thread(thd, thd_table); +#endif } mysql_mutex_unlock(&in_use->LOCK_thd_data); } diff --git a/sql/sql_builtin.cc.in b/sql/sql_builtin.cc.in index 63850650ac9..2de475b0a76 100644 --- a/sql/sql_builtin.cc.in +++ b/sql/sql_builtin.cc.in @@ -25,7 +25,11 @@ extern #endif builtin_maria_plugin @mysql_mandatory_plugins@ @mysql_optional_plugins@ - builtin_maria_binlog_plugin, builtin_maria_mysql_password_plugin; + builtin_maria_binlog_plugin, +#ifdef WITH_WSREP + builtin_wsrep_plugin@mysql_plugin_defs@, +#endif /* WITH_WSREP */ + builtin_maria_mysql_password_plugin; struct st_maria_plugin *mysql_optional_plugins[]= { @@ -35,5 +39,8 @@ struct st_maria_plugin *mysql_optional_plugins[]= struct st_maria_plugin *mysql_mandatory_plugins[]= { builtin_maria_binlog_plugin, builtin_maria_mysql_password_plugin, +#ifdef WITH_WSREP + builtin_wsrep_plugin@mysql_plugin_defs@, +#endif /* WITH_WSREP */ @mysql_mandatory_plugins@ 0 }; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 238bf46e528..71df97dd964 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -62,6 +62,9 @@ #include "debug_sync.h" #include "sql_parse.h" // is_update_query #include "sql_callback.h" +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif #include "sql_connect.h" /* @@ -782,6 +785,173 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length, return buffer; } +#ifdef WITH_WSREP +extern int wsrep_on(void *thd) +{ + return (int)(WSREP(((THD*)thd))); +} +extern "C" bool wsrep_thd_is_wsrep_on(THD *thd) +{ + return thd->variables.wsrep_on; +} + +extern "C" bool wsrep_consistency_check(void *thd) +{ + return ((THD*)thd)->wsrep_consistency_check == CONSISTENCY_CHECK_RUNNING; +} + +extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode) +{ + thd->wsrep_exec_mode= mode; +} +extern "C" void wsrep_thd_set_query_state( + THD *thd, enum wsrep_query_state state) +{ + thd->wsrep_query_state= state; +} +extern "C" void wsrep_thd_set_conflict_state( + THD *thd, enum wsrep_conflict_state state) +{ + thd->wsrep_conflict_state= state; +} + + +extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd) +{ + return thd->wsrep_exec_mode; +} + +extern "C" const char *wsrep_thd_exec_mode_str(THD *thd) +{ + return + (!thd) ? "void" : + (thd->wsrep_exec_mode == LOCAL_STATE) ? "local" : + (thd->wsrep_exec_mode == REPL_RECV) ? "applier" : + (thd->wsrep_exec_mode == TOTAL_ORDER) ? "total order" : + (thd->wsrep_exec_mode == LOCAL_COMMIT) ? "local commit" : "void"; +} + +extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd) +{ + return thd->wsrep_query_state; +} + +extern "C" const char *wsrep_thd_query_state_str(THD *thd) +{ + return + (!thd) ? "void" : + (thd->wsrep_query_state == QUERY_IDLE) ? "idle" : + (thd->wsrep_query_state == QUERY_EXEC) ? "executing" : + (thd->wsrep_query_state == QUERY_COMMITTING) ? "committing" : + (thd->wsrep_query_state == QUERY_EXITING) ? "exiting" : + (thd->wsrep_query_state == QUERY_ROLLINGBACK) ? "rolling back" : "void"; +} + +extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd) +{ + return thd->wsrep_conflict_state; +} +extern "C" const char *wsrep_thd_conflict_state_str(THD *thd) +{ + return + (!thd) ? "void" : + (thd->wsrep_conflict_state == NO_CONFLICT) ? "no conflict" : + (thd->wsrep_conflict_state == MUST_ABORT) ? "must abort" : + (thd->wsrep_conflict_state == ABORTING) ? "aborting" : + (thd->wsrep_conflict_state == MUST_REPLAY) ? "must replay" : + (thd->wsrep_conflict_state == REPLAYING) ? "replaying" : + (thd->wsrep_conflict_state == RETRY_AUTOCOMMIT) ? "retrying" : + (thd->wsrep_conflict_state == CERT_FAILURE) ? "cert failure" : "void"; +} + +extern "C" wsrep_trx_handle_t* wsrep_thd_trx_handle(THD *thd) +{ + return &thd->wsrep_trx_handle; +} + +extern "C"void wsrep_thd_LOCK(THD *thd) +{ + mysql_mutex_lock(&thd->LOCK_wsrep_thd); +} +extern "C"void wsrep_thd_UNLOCK(THD *thd) +{ + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); +} +extern "C" time_t wsrep_thd_query_start(THD *thd) +{ + return thd->query_start(); +} +extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd) +{ + return thd->wsrep_rand; +} +extern "C" my_thread_id wsrep_thd_thread_id(THD *thd) +{ + return thd->thread_id; +} +extern "C" wsrep_seqno_t wsrep_thd_trx_seqno(THD *thd) +{ + return (thd) ? thd->wsrep_trx_seqno : -1; +} +extern "C" query_id_t wsrep_thd_query_id(THD *thd) +{ + return thd->query_id; +} +extern "C" char *wsrep_thd_query(THD *thd) +{ + return (thd) ? thd->query() : NULL; +} +extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd) +{ + return thd->wsrep_last_query_id; +} +extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id) +{ + thd->wsrep_last_query_id= id; +} +extern "C" void wsrep_thd_awake(THD* bf_thd, THD *thd, my_bool signal) +{ + if (signal) + { + thd->wsrep_bf_thd = bf_thd; + mysql_mutex_lock(&thd->LOCK_thd_data); + thd->awake(KILL_QUERY); + mysql_mutex_unlock(&thd->LOCK_thd_data); + } + else + { + mysql_mutex_lock(&LOCK_wsrep_replaying); + mysql_cond_broadcast(&COND_wsrep_replaying); + mysql_mutex_unlock(&LOCK_wsrep_replaying); + } +} + +extern int +wsrep_trx_order_before(void *thd1, void *thd2) +{ + if (((THD*)thd1)->wsrep_trx_seqno < ((THD*)thd2)->wsrep_trx_seqno) { + WSREP_DEBUG("BF conflict, order: %lld %lld\n", + (long long)((THD*)thd1)->wsrep_trx_seqno, + (long long)((THD*)thd2)->wsrep_trx_seqno); + return 1; + } + WSREP_DEBUG("waiting for BF, trx order: %lld %lld\n", + (long long)((THD*)thd1)->wsrep_trx_seqno, + (long long)((THD*)thd2)->wsrep_trx_seqno); + return 0; +} +extern "C" int +wsrep_trx_is_aborting(void *thd_ptr) +{ + if (thd_ptr) { + if ((((THD *)thd_ptr)->wsrep_conflict_state == MUST_ABORT) || + (((THD *)thd_ptr)->wsrep_conflict_state == ABORTING)) { + return 1; + } + } + return 0; +} +#endif /** Implementation of Drop_table_error_handler::handle_condition(). @@ -810,7 +980,11 @@ bool Drop_table_error_handler::handle_condition(THD *thd, } +#ifdef WITH_WSREP +THD::THD(bool is_applier) +#else THD::THD() +#endif :Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION, /* statement id */ 0), rli_fake(0), rli_slave(NULL), @@ -842,6 +1016,11 @@ THD::THD() bootstrap(0), derived_tables_processing(FALSE), spcont(NULL), +#ifdef WITH_WSREP + wsrep_applier(is_applier), + wsrep_applier_closing(FALSE), + wsrep_client_thread(0), +#endif m_parser_state(NULL), #if defined(ENABLED_DEBUG_SYNC) debug_sync_control(0), @@ -955,6 +1134,23 @@ THD::THD() m_command=COM_CONNECT; *scramble= '\0'; +#ifdef WITH_WSREP + mysql_mutex_init(key_LOCK_wsrep_thd, &LOCK_wsrep_thd, MY_MUTEX_INIT_FAST); + mysql_cond_init(key_COND_wsrep_thd, &COND_wsrep_thd, NULL); + wsrep_trx_handle.trx_id = WSREP_UNDEFINED_TRX_ID; + wsrep_trx_handle.opaque = NULL; + //wsrep_retry_autocommit= ::wsrep_retry_autocommit; + wsrep_retry_counter = 0; + wsrep_PA_safe = true; + wsrep_seqno_changed = false; + wsrep_retry_query = NULL; + wsrep_retry_query_len = 0; + wsrep_retry_command = COM_CONNECT; + wsrep_consistency_check = NO_CONSISTENCY_CHECK; + wsrep_status_vars = 0; + wsrep_mysql_replicated = 0; + wsrep_bf_thd = NULL; +#endif /* Call to init() below requires fully initialized Open_tables_state. */ reset_open_tables_state(this); @@ -994,6 +1190,13 @@ THD::THD() my_rnd_init(&rand, tmp + (ulong) &rand, tmp + (ulong) ::global_query_id); substitute_null_with_insert_id = FALSE; thr_lock_info_init(&lock_info); /* safety: will be reset after start */ +#ifdef WITH_WSREP + lock_info.mysql_thd= (void *)this; + lock_info.in_lock_tables= false; +#ifdef WSREP_PROC_INFO + wsrep_info[sizeof(wsrep_info) - 1] = '\0'; /* make sure it is 0-terminated */ +#endif /* WSREP_PROC_INFO */ +#endif /* WITH_WSREP */ m_internal_handler= NULL; m_binlog_invoker= FALSE; @@ -1306,7 +1509,21 @@ void THD::init(void) reset_current_stmt_binlog_format_row(); set_status_var_init(); bzero((char *) &org_status_var, sizeof(org_status_var)); - +#ifdef WITH_WSREP + wsrep_exec_mode= wsrep_applier ? REPL_RECV : LOCAL_STATE; + wsrep_conflict_state= NO_CONFLICT; + wsrep_query_state= QUERY_IDLE; + wsrep_last_query_id= 0; + wsrep_trx_seqno= 0; + wsrep_converted_lock_session= false; + wsrep_retry_counter= 0; + wsrep_rli= NULL; + wsrep_PA_safe= true; + wsrep_seqno_changed= false; + wsrep_consistency_check = NO_CONSISTENCY_CHECK; + wsrep_mysql_replicated = 0; + wsrep_bf_thd = NULL; +#endif if (variables.sql_log_bin) variables.option_bits|= OPTION_BIN_LOG; else @@ -1504,6 +1721,13 @@ THD::~THD() mysys_var=0; // Safety (shouldn't be needed) mysql_mutex_unlock(&LOCK_thd_data); +#ifdef WITH_WSREP + mysql_mutex_lock(&LOCK_wsrep_thd); + mysql_mutex_unlock(&LOCK_wsrep_thd); + mysql_mutex_destroy(&LOCK_wsrep_thd); + if (wsrep_rli) delete wsrep_rli; + if (wsrep_status_vars) wsrep->stats_free(wsrep, wsrep_status_vars); +#endif /* Close connection */ #ifndef EMBEDDED_LIBRARY if (net.vio) @@ -1678,6 +1902,9 @@ void THD::awake(killed_state state_to_set) /* Interrupt target waiting inside a storage engine. */ if (state_to_set != NOT_KILLED) +#ifdef WITH_WSREP + if (!wsrep_bf_thd || wsrep_bf_thd->wsrep_exec_mode == LOCAL_STATE) +#endif /* WITH_WSREP */ ha_kill_query(this, thd_kill_level(this)); /* Broadcast a condition to kick the target if it is waiting on it. */ @@ -1944,6 +2171,13 @@ void THD::cleanup_after_query() /* reset table map for multi-table update */ table_map_for_update= 0; m_binlog_invoker= FALSE; +#ifdef WITH_WSREP + if (TOTAL_ORDER == wsrep_exec_mode) + { + wsrep_exec_mode = LOCAL_STATE; + } + //wsrep_trx_seqno = 0; +#endif /* WITH_WSREP */ #ifndef EMBEDDED_LIBRARY if (rli_slave) @@ -2353,6 +2587,13 @@ bool sql_exchange::escaped_given(void) bool select_send::send_result_set_metadata(List<Item> &list, uint flags) { bool res; +#ifdef WITH_WSREP + if (WSREP(thd) && thd->wsrep_retry_query) + { + WSREP_DEBUG("skipping select metadata"); + return FALSE; + } +#endif /* WITH_WSREP */ if (!(res= thd->protocol->send_result_set_metadata(&list, flags))) is_result_set_started= 1; return res; @@ -4103,8 +4344,13 @@ extern "C" int thd_non_transactional_update(const MYSQL_THD thd) extern "C" int thd_binlog_format(const MYSQL_THD thd) { +#ifdef WITH_WSREP + if (((WSREP(thd) && wsrep_emulate_bin_log) || mysql_bin_log.is_open()) && + (thd->variables.option_bits & OPTION_BIN_LOG)) +#else if (mysql_bin_log.is_open() && (thd->variables.option_bits & OPTION_BIN_LOG)) - return (int) thd->variables.binlog_format; +#endif + return (int) WSREP_FORMAT(thd->variables.binlog_format); else return BINLOG_FORMAT_UNSPEC; } @@ -4796,7 +5042,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) binlog by filtering rules. */ if (mysql_bin_log.is_open() && (variables.option_bits & OPTION_BIN_LOG) && - !(variables.binlog_format == BINLOG_FORMAT_STMT && + !(WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_STMT && !binlog_filter->db_ok(db))) { /* @@ -4960,7 +5206,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) */ my_error((error= ER_BINLOG_ROW_INJECTION_AND_STMT_ENGINE), MYF(0)); } - else if (variables.binlog_format == BINLOG_FORMAT_ROW && + else if (WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_ROW && sqlcom_can_generate_row_events(this)) { /* @@ -4989,7 +5235,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) else { /* binlog_format = STATEMENT */ - if (variables.binlog_format == BINLOG_FORMAT_STMT) + if (WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_STMT) { if (lex->is_stmt_row_injection()) { @@ -5006,7 +5252,14 @@ int THD::decide_logging_format(TABLE_LIST *tables) 5. Error: Cannot modify table that uses a storage engine limited to row-logging when binlog_format = STATEMENT */ +#ifdef WITH_WSREP + if (!WSREP(this) || wsrep_exec_mode == LOCAL_STATE) + { +#endif /* WITH_WSREP */ my_error((error= ER_BINLOG_STMT_MODE_AND_ROW_ENGINE), MYF(0), ""); +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ } else if (is_write && (unsafe_flags= lex->get_stmt_unsafe_flags()) != 0) { @@ -5054,7 +5307,7 @@ int THD::decide_logging_format(TABLE_LIST *tables) "and binlog_filter->db_ok(db) = %d", mysql_bin_log.is_open(), (variables.option_bits & OPTION_BIN_LOG), - variables.binlog_format, + WSREP_FORMAT(variables.binlog_format), binlog_filter->db_ok(db))); #endif @@ -5287,7 +5540,13 @@ int THD::binlog_write_row(TABLE* table, bool is_trans, MY_BITMAP const* cols, size_t colcnt, uchar const *record) { +#ifdef WITH_WSREP + DBUG_ASSERT(is_current_stmt_binlog_format_row() && + ((WSREP(this) && wsrep_emulate_bin_log) || + mysql_bin_log.is_open())); +#else DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open()); +#endif /* Pack records into format for transfer. We are allocating more @@ -5317,7 +5576,13 @@ int THD::binlog_update_row(TABLE* table, bool is_trans, const uchar *before_record, const uchar *after_record) { +#ifdef WITH_WSREP + DBUG_ASSERT(is_current_stmt_binlog_format_row() && + ((WSREP(this) && wsrep_emulate_bin_log) + || mysql_bin_log.is_open())); +#else DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open()); +#endif size_t const before_maxlen = max_row_length(table, before_record); size_t const after_maxlen = max_row_length(table, after_record); @@ -5362,7 +5627,13 @@ int THD::binlog_delete_row(TABLE* table, bool is_trans, MY_BITMAP const* cols, size_t colcnt, uchar const *record) { +#ifdef WITH_WSREP + DBUG_ASSERT(is_current_stmt_binlog_format_row() && + ((WSREP(this) && wsrep_emulate_bin_log) + || mysql_bin_log.is_open())); +#else DBUG_ASSERT(is_current_stmt_binlog_format_row() && mysql_bin_log.is_open()); +#endif /* Pack records into format for transfer. We are allocating more @@ -5393,7 +5664,11 @@ int THD::binlog_remove_pending_rows_event(bool clear_maps, { DBUG_ENTER("THD::binlog_remove_pending_rows_event"); +#ifdef WITH_WSREP + if (!(WSREP_EMULATE_BINLOG(this) || mysql_bin_log.is_open())) +#else if (!mysql_bin_log.is_open()) +#endif DBUG_RETURN(0); mysql_bin_log.remove_pending_rows_event(this, is_transactional); @@ -5412,7 +5687,11 @@ int THD::binlog_flush_pending_rows_event(bool stmt_end, bool is_transactional) mode: it might be the case that we left row-based mode before flushing anything (e.g., if we have explicitly locked tables). */ +#ifdef WITH_WSREP + if (!(WSREP_EMULATE_BINLOG(this) || mysql_bin_log.is_open())) +#else if (!mysql_bin_log.is_open()) +#endif DBUG_RETURN(0); /* @@ -5660,8 +5939,12 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg, DBUG_ENTER("THD::binlog_query"); DBUG_PRINT("enter", ("qtype: %s query: '%-.*s'", show_query_type(qtype), (int) query_len, query_arg)); +#ifdef WITH_WSREP + DBUG_ASSERT(query_arg && (WSREP_EMULATE_BINLOG(this) + || mysql_bin_log.is_open())); +#else DBUG_ASSERT(query_arg && mysql_bin_log.is_open()); - +#endif /* If we are not in prelocked mode, mysql_unlock_tables() will be called after this binlog_query(), so we have to flush the pending diff --git a/sql/sql_class.h b/sql/sql_class.h index 5ae777fe817..3427c7ea00d 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -57,6 +57,15 @@ void set_thd_stage_info(void *thd, #include "my_apc.h" +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +struct wsrep_thd_shadow { + ulonglong options; + enum wsrep_exec_mode wsrep_exec_mode; + Vio *vio; + ulong tx_isolation; +}; +#endif class Reprepare_observer; class Relay_log_info; class Rpl_filter; @@ -613,6 +622,11 @@ typedef struct system_variables ulong wt_timeout_short, wt_deadlock_search_depth_short; ulong wt_timeout_long, wt_deadlock_search_depth_long; +#ifdef WITH_WSREP + my_bool wsrep_on; + my_bool wsrep_causal_reads; + ulong wsrep_retry_autocommit; +#endif double long_query_time_double; my_bool pseudo_slave_mode; @@ -1015,6 +1029,9 @@ struct st_savepoint { /** State of metadata locks before this savepoint was set. */ MDL_savepoint mdl_savepoint; }; +#ifdef WITH_WSREP +void wsrep_cleanup_transaction(THD *thd); // THD.transactions.cleanup calls it +#endif enum xa_states {XA_NOTR=0, XA_ACTIVE, XA_IDLE, XA_PREPARED, XA_ROLLBACK_ONLY}; extern const char *xa_state_names[]; @@ -1860,7 +1877,7 @@ public: int is_current_stmt_binlog_format_row() const { DBUG_ASSERT(current_stmt_binlog_format == BINLOG_FORMAT_STMT || current_stmt_binlog_format == BINLOG_FORMAT_ROW); - return current_stmt_binlog_format == BINLOG_FORMAT_ROW; + return (WSREP_FORMAT((ulong)current_stmt_binlog_format) == BINLOG_FORMAT_ROW); } private: @@ -1918,7 +1935,11 @@ public: */ CHANGED_TABLE_LIST* changed_tables; MEM_ROOT mem_root; // Transaction-life memory allocation pool +#ifdef WITH_WSREP + void cleanup(THD *thd) +#else void cleanup() +#endif { DBUG_ENTER("thd::cleanup"); changed_tables= 0; @@ -1932,6 +1953,11 @@ public: if (!xid_state.rm_error) xid_state.xid.null(); free_root(&mem_root,MYF(MY_KEEP_PREALLOC)); +#ifdef WITH_WSREP + // Todo: convert into a plugin method + // wsrep's post-commit. LOCAL_COMMIT designates wsrep's commit was ok + if (WSREP(thd)) wsrep_cleanup_transaction(thd); +#endif /* WITH_WSREP */ DBUG_VOID_RETURN; } my_bool is_active() @@ -2464,6 +2490,36 @@ public: query_id_t first_query_id; } binlog_evt_union; +#ifdef WITH_WSREP + const bool wsrep_applier; /* dedicated slave applier thread */ + bool wsrep_applier_closing; /* applier marked to close */ + bool wsrep_client_thread; /* to identify client threads*/ + enum wsrep_exec_mode wsrep_exec_mode; + query_id_t wsrep_last_query_id; + enum wsrep_query_state wsrep_query_state; + enum wsrep_conflict_state wsrep_conflict_state; + mysql_mutex_t LOCK_wsrep_thd; + mysql_cond_t COND_wsrep_thd; + wsrep_seqno_t wsrep_trx_seqno; + uint32 wsrep_rand; + Relay_log_info* wsrep_rli; + bool wsrep_converted_lock_session; + wsrep_trx_handle_t wsrep_trx_handle; + bool wsrep_seqno_changed; +#ifdef WSREP_PROC_INFO + char wsrep_info[128]; /* string for dynamic proc info */ +#endif /* WSREP_PROC_INFO */ + ulong wsrep_retry_counter; // of autocommit + bool wsrep_PA_safe; + char* wsrep_retry_query; + size_t wsrep_retry_query_len; + enum enum_server_command wsrep_retry_command; + enum wsrep_consistency_check_mode + wsrep_consistency_check; + wsrep_stats_var* wsrep_status_vars; + int wsrep_mysql_replicated; + THD* wsrep_bf_thd; +#endif /* WITH_WSREP */ /** Internal parser state. Note that since the parser is not re-entrant, we keep only one parser @@ -2495,7 +2551,11 @@ public: /* Debug Sync facility. See debug_sync.cc. */ struct st_debug_sync_control *debug_sync_control; #endif /* defined(ENABLED_DEBUG_SYNC) */ +#ifdef WITH_WSREP + THD(bool is_applier = false); +#else THD(); +#endif ~THD(); void init(void); @@ -2967,7 +3027,7 @@ public: tests fail and so force them to propagate the lex->binlog_row_based_if_mixed upwards to the caller. */ - if ((variables.binlog_format == BINLOG_FORMAT_MIXED) && + if ((WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_MIXED) && (in_sub_stmt == 0)) set_current_stmt_binlog_format_row(); @@ -3019,7 +3079,7 @@ public: show_system_thread(system_thread))); if (in_sub_stmt == 0) { - if (variables.binlog_format == BINLOG_FORMAT_ROW) + if (WSREP_FORMAT(variables.binlog_format) == BINLOG_FORMAT_ROW) set_current_stmt_binlog_format_row(); else if (temporary_tables == NULL) set_current_stmt_binlog_format_stmt(); diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc index c3f2bb0ca11..b3af783c566 100644 --- a/sql/sql_connect.cc +++ b/sql/sql_connect.cc @@ -44,6 +44,9 @@ HASH global_index_stats; extern mysql_mutex_t LOCK_global_user_client_stats; extern mysql_mutex_t LOCK_global_table_stats; extern mysql_mutex_t LOCK_global_index_stats; +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif /* Get structure for logging connection data for the current user @@ -990,7 +993,11 @@ bool setup_connection_thread_globals(THD *thd) { if (thd->store_globals()) { +#ifdef WITH_WSREP + close_connection(thd, ER_OUT_OF_RESOURCES, 1); +#else close_connection(thd, ER_OUT_OF_RESOURCES); +#endif statistic_increment(aborted_connects,&LOCK_status); MYSQL_CALLBACK(thd->scheduler, end_thread, (thd, 0)); return 1; // Error @@ -1063,6 +1070,17 @@ bool login_connection(THD *thd) void end_connection(THD *thd) { NET *net= &thd->net; +#ifdef WITH_WSREP + if (WSREP(thd)) + { + wsrep_status_t rcode= wsrep->free_connection(wsrep, thd->thread_id); + if (rcode) { + WSREP_WARN("wsrep failed to free connection context: %lu, code: %d", + thd->thread_id, rcode); + } + } + thd->wsrep_client_thread= 0; +#endif plugin_thdvar_cleanup(thd); if (thd->user_connect) @@ -1195,6 +1213,9 @@ bool thd_prepare_connection(THD *thd) (char *) thd->security_ctx->host_or_ip); prepare_new_connection_state(thd); +#ifdef WITH_WSREP + thd->wsrep_client_thread= 1; +#endif /* WITH_WSREP */ return FALSE; } @@ -1218,7 +1239,11 @@ void do_handle_one_connection(THD *thd_arg) if (MYSQL_CALLBACK_ELSE(thd->scheduler, init_new_connection_thread, (), 0)) { +#ifdef WITH_WSREP + close_connection(thd, ER_OUT_OF_RESOURCES, 1); +#else close_connection(thd, ER_OUT_OF_RESOURCES); +#endif statistic_increment(aborted_connects,&LOCK_status); MYSQL_CALLBACK(thd->scheduler, end_thread, (thd, 0)); return; @@ -1268,9 +1293,21 @@ void do_handle_one_connection(THD *thd_arg) break; } end_connection(thd); - + +#ifdef WITH_WSREP + if (WSREP(thd)) + { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_query_state= QUERY_EXITING; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } +#endif end_thread: +#ifdef WITH_WSREP + close_connection(thd, 0, 1); +#else close_connection(thd); +#endif if (thd->userstat_running) update_global_user_stats(thd, create_user, time(NULL)); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index d0a83eac189..1fed2a37e15 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -424,7 +424,11 @@ cleanup: /* See similar binlogging code in sql_update.cc, for comments */ if ((error < 0) || thd->transaction.stmt.modified_non_trans_table) { +#ifdef WITH_WSREP + if ((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open())) +#else if (mysql_bin_log.is_open()) +#endif { int errcode= 0; if (error < 0) @@ -875,7 +879,11 @@ void multi_delete::abort_result_set() /* there is only side effects; to binlog with the error */ +#ifdef WITH_WSREP + if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) +#else if (mysql_bin_log.is_open()) +#endif { int errcode= query_error_code(thd, thd->killed == NOT_KILLED); /* possible error of writing binary log is ignored deliberately */ @@ -1051,7 +1059,11 @@ bool multi_delete::send_eof() } if ((local_error == 0) || thd->transaction.stmt.modified_non_trans_table) { +#ifdef WITH_WSREP + if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) +#else if (mysql_bin_log.is_open()) +#endif { int errcode= 0; if (local_error == 0) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 4f025c7c335..34b4385ce94 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1017,7 +1017,11 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, thd->transaction.stmt.modified_non_trans_table || was_insert_delayed) { +#ifdef WITH_WSREP + if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) +#else if (mysql_bin_log.is_open()) +#endif { int errcode= 0; if (error <= 0) @@ -3641,8 +3645,15 @@ bool select_insert::send_eof() DBUG_PRINT("enter", ("trans_table=%d, table_type='%s'", trans_table, table->file->table_type())); +#ifdef WITH_WSREP + error= (thd->wsrep_conflict_state == MUST_ABORT || + thd->wsrep_conflict_state == CERT_FAILURE) ? -1 : + (thd->locked_tables_mode <= LTM_LOCK_TABLES ? + table->file->ha_end_bulk_insert() : 0); +#else error= (thd->locked_tables_mode <= LTM_LOCK_TABLES ? table->file->ha_end_bulk_insert() : 0); +#endif /* WITH_WSREP */ if (!error && thd->is_error()) error= thd->stmt_da->sql_errno(); @@ -3670,8 +3681,13 @@ bool select_insert::send_eof() events are in the transaction cache and will be written when ha_autocommit_or_rollback() is issued below. */ +#ifdef WITH_WSREP + if ((WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) && + (!error || thd->transaction.stmt.modified_non_trans_table)) +#else if (mysql_bin_log.is_open() && (!error || thd->transaction.stmt.modified_non_trans_table)) +#endif { int errcode= 0; if (!error) @@ -3754,7 +3770,11 @@ void select_insert::abort_result_set() { if (!can_rollback_data()) thd->transaction.all.modified_non_trans_table= TRUE; +#ifdef WITH_WSREP + if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) +#else if (mysql_bin_log.is_open()) +#endif { int errcode= query_error_code(thd, thd->killed == NOT_KILLED); /* error of writing binary log is ignored */ @@ -4141,7 +4161,11 @@ select_create::binlog_show_create_table(TABLE **tables, uint count) /* show_database */ TRUE); DBUG_ASSERT(result == 0); /* store_create_info() always return 0 */ +#ifdef WITH_WSREP + if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) +#else if (mysql_bin_log.is_open()) +#endif /* WITH_WSREP */ { int errcode= query_error_code(thd, thd->killed == NOT_KILLED); result= thd->binlog_query(THD::STMT_QUERY_TYPE, @@ -4151,6 +4175,9 @@ select_create::binlog_show_create_table(TABLE **tables, uint count) /* suppress_use */ FALSE, errcode); } +#ifdef WITH_WSREP + ha_wsrep_fake_trx_id(thd); +#endif return result; } @@ -4207,6 +4234,18 @@ bool select_create::send_eof() { trans_commit_stmt(thd); trans_commit_implicit(thd); +#ifdef WITH_WSREP + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state != NO_CONFLICT) + { + WSREP_DEBUG("select_create commit failed, thd: %lu err: %d %s", + thd->thread_id, thd->wsrep_conflict_state, thd->query()); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + abort_result_set(); + return TRUE; + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); +#endif /* WITH_WSREP */ } table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index fbe5bcd57f2..1ba132b534b 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1574,6 +1574,17 @@ int lex_one_token(void *arg, void *yythd) } else { +#ifdef WITH_WSREP + if (version == 99997 && thd->wsrep_exec_mode == LOCAL_STATE) + { + WSREP_DEBUG("consistency check: %s", thd->query()); + thd->wsrep_consistency_check= CONSISTENCY_CHECK_DECLARED; + lip->yySkipn(5); + lip->set_echo(TRUE); + state=MY_LEX_START; + break; /* Do not treat contents as a comment. */ + } +#endif /* WITH_WSREP */ /* Patch and skip the conditional comment to avoid it being propagated infinitely (eg. to a slave). diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ea0a19fc5f3..888aebd52b2 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -104,6 +104,16 @@ #include "../storage/maria/ha_maria.h" #endif +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#include "rpl_rli.h" +static void wsrep_client_rollback(THD *thd); + +extern Format_description_log_event *wsrep_format_desc; + +static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, + Parser_state *parser_state); +#endif /* WITH_WSREP */ /** @defgroup Runtime_Environment Runtime Environment @{ @@ -596,6 +606,13 @@ bool is_log_table_write_query(enum enum_sql_command command) return (sql_command_flags[command] & CF_WRITE_LOGS_COMMAND) != 0; } +#ifdef WITH_WSREP +bool is_show_query(enum enum_sql_command command) +{ + DBUG_ASSERT(command >= 0 && command <= SQLCOM_END); + return (sql_command_flags[command] & CF_STATUS_COMMAND) != 0; +} +#endif void execute_init_command(THD *thd, LEX_STRING *init_command, mysql_rwlock_t *var_lock) { @@ -792,8 +809,12 @@ void do_handle_bootstrap(THD *thd) if (my_thread_init() || thd->store_globals()) { #ifndef EMBEDDED_LIBRARY +#ifdef WITH_WSREP + close_connection(thd, ER_OUT_OF_RESOURCES, 1); +#else close_connection(thd, ER_OUT_OF_RESOURCES); #endif +#endif thd->fatal_error(); goto end; } @@ -866,7 +887,18 @@ bool do_command(THD *thd) NET *net= &thd->net; enum enum_server_command command; DBUG_ENTER("do_command"); - +#ifdef WITH_WSREP + if (WSREP(thd)) + { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_query_state= QUERY_IDLE; + if (thd->wsrep_conflict_state==MUST_ABORT) + { + wsrep_client_rollback(thd); + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } +#endif /* indicator of uninitialized lex => normal flow of errors handling (see my_message_sql) @@ -915,6 +947,30 @@ bool do_command(THD *thd) thd->m_server_idle= TRUE; packet_length= my_net_read(net); thd->m_server_idle= FALSE; +#ifdef WITH_WSREP + if (WSREP(thd)) { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + + /* these THD's are aborted or are aborting during being idle */ + if (thd->wsrep_conflict_state == ABORTING) + { + while (thd->wsrep_conflict_state == ABORTING) { + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + my_sleep(1000); + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + } + thd->store_globals(); + } + else if (thd->wsrep_conflict_state == ABORTED) + { + thd->store_globals(); + thd->wsrep_bf_thd = NULL; + } + + thd->wsrep_query_state= QUERY_EXEC; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } +#endif /* WITH_WSREP */ if (packet_length == packet_error) { @@ -922,6 +978,17 @@ bool do_command(THD *thd) net->error, vio_description(net->vio))); +#ifdef WITH_WSREP + if (WSREP(thd)) { + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state == MUST_ABORT) + { + DBUG_PRINT("wsrep",("aborted for wsrep rollback: %lu", thd->real_id)); + wsrep_client_rollback(thd); + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } +#endif /* Instrument this broken statement as "statement/com/error" */ thd->m_statement_psi= MYSQL_REFINE_STATEMENT(thd->m_statement_psi, com_statement_info[COM_END]. @@ -976,12 +1043,54 @@ bool do_command(THD *thd) vio_description(net->vio), command, command_name[command].str)); +#ifdef WITH_WSREP + if (WSREP(thd)) { + /* + * bail out if DB snapshot has not been installed. We however, + * allow queries "SET" and "SHOW", they are trapped later in execute_command + */ + if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready && + command != COM_QUERY && + command != COM_PING && + command != COM_QUIT && + command != COM_PROCESS_INFO && + command != COM_PROCESS_KILL && + command != COM_SET_OPTION && + command != COM_SHUTDOWN && + command != COM_SLEEP && + command != COM_STATISTICS && + command != COM_TIME && + command != COM_END + ) { + my_error(ER_UNKNOWN_COM_ERROR, MYF(0), + "WSREP has not yet prepared node for application use"); + thd->protocol->end_statement(); + return_value= FALSE; + goto out; + } + } +#endif /* Restore read timeout value */ my_net_set_read_timeout(net, thd->variables.net_read_timeout); DBUG_ASSERT(packet_length); return_value= dispatch_command(command, thd, packet+1, (uint) (packet_length-1)); - +#ifdef WITH_WSREP + if (WSREP(thd)) { + while (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT) + { + return_value= dispatch_command(command, thd, thd->wsrep_retry_query, + thd->wsrep_retry_query_len); + } + } + if (thd->wsrep_retry_query && thd->wsrep_conflict_state != REPLAYING) + { + my_free(thd->wsrep_retry_query); + thd->wsrep_retry_query = NULL; + thd->wsrep_retry_query_len = 0; + thd->wsrep_retry_command = COM_CONNECT; + } +#endif out: /* The statement instrumentation must be closed in all cases. */ DBUG_ASSERT(thd->m_statement_psi == NULL); @@ -1057,6 +1166,33 @@ static my_bool deny_updates_if_read_only_option(THD *thd, DBUG_RETURN(FALSE); } +#ifdef WITH_WSREP +static my_bool wsrep_read_only_option(THD *thd, TABLE_LIST *all_tables) +{ + int opt_readonly_saved = opt_readonly; + ulong flag_saved = (ulong)(thd->security_ctx->master_access & SUPER_ACL); + + opt_readonly = 0; + thd->security_ctx->master_access &= ~SUPER_ACL; + + my_bool ret = !deny_updates_if_read_only_option(thd, all_tables); + + opt_readonly = opt_readonly_saved; + thd->security_ctx->master_access |= flag_saved; + + return ret; +} + +static void wsrep_copy_query(THD *thd) +{ + thd->wsrep_retry_command = thd->get_command(); + thd->wsrep_retry_query_len = thd->query_length(); + thd->wsrep_retry_query = (char *)my_malloc( + thd->wsrep_retry_query_len + 1, MYF(0)); + strncpy(thd->wsrep_retry_query, thd->query(), thd->wsrep_retry_query_len); + thd->wsrep_retry_query[thd->wsrep_retry_query_len] = '\0'; +} +#endif /* WITH_WSREP */ /** Perform one connection-level (COM_XXXX) command. @@ -1086,6 +1222,43 @@ bool dispatch_command(enum enum_server_command command, THD *thd, DBUG_ENTER("dispatch_command"); DBUG_PRINT("info", ("command: %d", command)); +#ifdef WITH_WSREP + if (WSREP(thd)) { + if (!thd->in_multi_stmt_transaction_mode()) + { + thd->wsrep_PA_safe= true; + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_query_state= QUERY_EXEC; + if (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT) + { + thd->wsrep_conflict_state= NO_CONFLICT; + } + if (thd->wsrep_conflict_state== MUST_ABORT) + { + wsrep_client_rollback(thd); + } + if (thd->wsrep_conflict_state== ABORTED) + { + my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); + WSREP_DEBUG("Deadlock error for: %s", thd->query()); + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + thd->killed = NOT_KILLED; + thd->mysys_var->abort = 0; + thd->wsrep_conflict_state = NO_CONFLICT; + thd->wsrep_retry_counter = 0; + thd->wsrep_bf_thd = NULL; + /* + Increment threads running to compensate dec_thread_running() called + after dispatch_end label. + */ + inc_thread_running(); + goto dispatch_end; + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } +#endif /* WITH_WSREP */ #if defined(ENABLED_PROFILING) thd->profiling.start_new_query(); #endif @@ -1271,7 +1444,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd, if (parser_state.init(thd, thd->query(), thd->query_length())) break; +#ifdef WITH_WSREP + wsrep_mysql_parse(thd, thd->query(), thd->query_length(), &parser_state); +#else mysql_parse(thd, thd->query(), thd->query_length(), &parser_state); +#endif while (!thd->killed && (parser_state.m_lip.found_semicolon != NULL) && ! thd->is_error()) @@ -1337,10 +1514,19 @@ bool dispatch_command(enum enum_server_command command, THD *thd, Count each statement from the client. */ statistic_increment(thd->status_var.questions, &LOCK_status); +#ifdef WITH_WSREP + if (!WSREP(thd)) + thd->set_time(); /* Reset the query start time. */ +#else thd->set_time(); /* Reset the query start time. */ +#endif parser_state.reset(beginning_of_next_stmt, length); /* TODO: set thd->lex->sql_command to SQLCOM_END here */ +#ifdef WITH_WSREP + wsrep_mysql_parse(thd, beginning_of_next_stmt, length, &parser_state); +#else mysql_parse(thd, beginning_of_next_stmt, length, &parser_state); +#endif } DBUG_PRINT("info",("query ready")); @@ -1659,6 +1845,23 @@ bool dispatch_command(enum enum_server_command command, THD *thd, my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0)); break; } +#ifdef WITH_WSREP + dispatch_end: + + if (WSREP(thd)) { + /* wsrep BF abort in query exec phase */ + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if ((thd->wsrep_conflict_state != REPLAYING) && + (thd->wsrep_conflict_state != RETRY_AUTOCOMMIT)) + { + thd->update_server_status(); + thd->protocol->end_statement(); + query_cache_end_of_result(thd); + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + } else { /* if (WSREP(thd))... */ +#endif /* WITH_WSREP */ DBUG_ASSERT(thd->derived_tables == NULL && (thd->open_tables == NULL || (thd->locked_tables_mode == LTM_LOCK_TABLES))); @@ -1668,6 +1871,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd, thd->update_server_status(); thd->protocol->end_statement(); query_cache_end_of_result(thd); +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ if (!thd->is_error() && !thd->killed_errno()) mysql_audit_general(thd, MYSQL_AUDIT_GENERAL_RESULT, 0, 0); @@ -2332,7 +2538,66 @@ mysql_execute_command(THD *thd) #ifdef HAVE_REPLICATION } /* endif unlikely slave */ #endif +#ifdef WITH_WSREP + if (WSREP(thd)) { + /* + change LOCK TABLE WRITE to transaction + */ + if (lex->sql_command== SQLCOM_LOCK_TABLES && wsrep_convert_LOCK_to_trx) + { + for (TABLE_LIST *table= all_tables; table; table= table->next_global) + { + if (table->lock_type >= TL_WRITE_ALLOW_WRITE) + { + lex->sql_command= SQLCOM_BEGIN; + thd->wsrep_converted_lock_session= true; + break; + } + } + } + if (lex->sql_command== SQLCOM_UNLOCK_TABLES && + thd->wsrep_converted_lock_session) + { + thd->wsrep_converted_lock_session= false; + lex->sql_command= SQLCOM_COMMIT; + lex->tx_release= TVL_NO; + } + /* + * bail out if DB snapshot has not been installed. We however, + * allow SET and SHOW queries + */ + if (thd->variables.wsrep_on && !thd->wsrep_applier && !wsrep_ready && + lex->sql_command != SQLCOM_SET_OPTION && + !is_show_query(lex->sql_command)) + { +#if DIRTY_HACK + /* Dirty hack for lp:1002714 - trying to recognize mysqldump connection + * and allow it to continue. Actuall mysqldump_magic_str may be longer + * and is obviously version dependent and may be issued by any client + * connection after which connection becomes non-replicating. */ + static char const mysqldump_magic_str[]= +"SELECT LOGFILE_GROUP_NAME, FILE_NAME, TOTAL_EXTENTS, INITIAL_SIZE, ENGINE, EXTRA FROM INFORMATION_SCHEMA.FILES WHERE FILE_TYPE = 'UNDO LOG' AND FILE_NAME IS NOT NULL"; + static const size_t mysqldump_magic_str_len= sizeof(mysqldump_magic_str) -1; + if (SQLCOM_SELECT != lex->sql_command || + thd->query_length() < mysqldump_magic_str_len || + strncmp(thd->query(), mysqldump_magic_str, mysqldump_magic_str_len)) + { +#endif /* DIRTY_HACK */ + my_error(ER_UNKNOWN_COM_ERROR, MYF(0), + "WSREP has not yet prepared node for application use"); + goto error; +#if DIRTY_HACK + } + else + { + /* mysqldump connection, allow all further queries to pass */ + thd->variables.wsrep_on= FALSE; + } +#endif /* DIRTY_HACK */ + } + } +#endif /* WITH_WSREP */ status_var_increment(thd->status_var.com_stat[lex->sql_command]); thd->progress.report_to_client= test(sql_command_flags[lex->sql_command] & CF_REPORT_PROGRESS); @@ -2404,6 +2669,9 @@ mysql_execute_command(THD *thd) #endif case SQLCOM_SHOW_STATUS_PROC: case SQLCOM_SHOW_STATUS_FUNC: +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error; +#endif /* WITH_WSREP */ if ((res= check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE))) goto error; @@ -2449,17 +2717,27 @@ mysql_execute_command(THD *thd) case SQLCOM_SHOW_PLUGINS: case SQLCOM_SHOW_FIELDS: case SQLCOM_SHOW_KEYS: +#ifndef WITH_WSREP case SQLCOM_SHOW_VARIABLES: case SQLCOM_SHOW_CHARSETS: case SQLCOM_SHOW_COLLATIONS: case SQLCOM_SHOW_STORAGE_ENGINES: case SQLCOM_SHOW_PROFILE: +#endif /* WITH_WSREP */ case SQLCOM_SHOW_CLIENT_STATS: case SQLCOM_SHOW_USER_STATS: case SQLCOM_SHOW_TABLE_STATS: case SQLCOM_SHOW_INDEX_STATS: case SQLCOM_SELECT: - { +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error; + case SQLCOM_SHOW_VARIABLES: + case SQLCOM_SHOW_CHARSETS: + case SQLCOM_SHOW_COLLATIONS: + case SQLCOM_SHOW_STORAGE_ENGINES: + case SQLCOM_SHOW_PROFILE: +#endif /* WITH_WSREP */ + { thd->status_var.last_query_cost= 0.0; /* @@ -2815,7 +3093,7 @@ case SQLCOM_PREPARE: */ if (thd->query_name_consts && mysql_bin_log.is_open() && - thd->variables.binlog_format == BINLOG_FORMAT_STMT && + WSREP_FORMAT(thd->variables.binlog_format) == BINLOG_FORMAT_STMT && !mysql_bin_log.is_query_in_union(thd, thd->query_id)) { List_iterator_fast<Item> it(select_lex->item_list); @@ -2926,6 +3204,12 @@ case SQLCOM_PREPARE: if (create_info.options & HA_LEX_CREATE_TMP_TABLE) thd->variables.option_bits|= OPTION_KEEP_LOG; /* regular create */ +#ifdef WITH_WSREP + if (!thd->is_current_stmt_binlog_format_row() || + !(create_info.options & HA_LEX_CREATE_TMP_TABLE)) + WSREP_TO_ISOLATION_BEGIN(create_table->db, create_table->table_name, + NULL) +#endif /* WITH_WSREP */ if (create_info.options & HA_LEX_CREATE_TABLE_LIKE) { /* CREATE TABLE ... LIKE ... */ @@ -2967,6 +3251,7 @@ end_with_restore_list: DBUG_ASSERT(first_table == all_tables && first_table != 0); if (check_one_table_access(thd, INDEX_ACL, all_tables)) goto error; /* purecov: inspected */ + WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL) /* Currently CREATE INDEX or DROP INDEX cause a full table rebuild and thus classify as slow administrative statements just like @@ -3063,6 +3348,7 @@ end_with_restore_list: #endif /* HAVE_REPLICATION */ case SQLCOM_RENAME_TABLE: { + WSREP_TO_ISOLATION_BEGIN(0, 0, first_table) if (execute_rename_table(thd, first_table, all_tables)) goto error; break; @@ -3090,6 +3376,10 @@ end_with_restore_list: goto error; #else { +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error; +#endif /* WITH_WSREP */ + /* Access check: SHOW CREATE TABLE require any privileges on the table level (ie @@ -3145,6 +3435,10 @@ end_with_restore_list: case SQLCOM_CHECKSUM: { DBUG_ASSERT(first_table == all_tables && first_table != 0); +#ifdef WITH_WSREP + if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) goto error; +#endif /* WITH_WSREP */ + if (check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE)) goto error; /* purecov: inspected */ @@ -3342,6 +3636,15 @@ end_with_restore_list: DBUG_ASSERT(first_table == all_tables && first_table != 0); if ((res= insert_precheck(thd, all_tables))) break; +#ifdef WITH_WSREP + if (lex->sql_command == SQLCOM_INSERT_SELECT && + thd->wsrep_consistency_check == CONSISTENCY_CHECK_DECLARED) + { + thd->wsrep_consistency_check = CONSISTENCY_CHECK_RUNNING; + WSREP_TO_ISOLATION_BEGIN(first_table->db, first_table->table_name, NULL); + } + +#endif /* INSERT...SELECT...ON DUPLICATE KEY UPDATE/REPLACE SELECT/ INSERT...IGNORE...SELECT can be unsafe, unless ORDER BY PRIMARY KEY @@ -3505,6 +3808,18 @@ end_with_restore_list: /* So that DROP TEMPORARY TABLE gets to binlog at commit/rollback */ thd->variables.option_bits|= OPTION_KEEP_LOG; } +#ifdef WITH_WSREP + for (TABLE_LIST *table= all_tables; table; table= table->next_global) + { + if (!lex->drop_temporary && + (!thd->is_current_stmt_binlog_format_row() || + !find_temporary_table(thd, table))) + { + WSREP_TO_ISOLATION_BEGIN(NULL, NULL, all_tables); + break; + } + } +#endif /* WITH_WSREP */ /* DDL and binlog write order are protected by metadata locks. */ res= mysql_rm_table(thd, first_table, lex->check_exists, lex->drop_temporary); @@ -3548,7 +3863,6 @@ end_with_restore_list: if (!mysql_change_db(thd, &db_str, FALSE)) my_ok(thd); - break; } @@ -3691,6 +4005,7 @@ end_with_restore_list: #endif if (check_access(thd, CREATE_ACL, lex->name.str, NULL, NULL, 1, 0)) break; + WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL) res= mysql_create_db(thd,(lower_case_table_names == 2 ? alias : lex->name.str), &create_info, 0); break; @@ -3720,6 +4035,7 @@ end_with_restore_list: #endif if (check_access(thd, DROP_ACL, lex->name.str, NULL, NULL, 1, 0)) break; + WSREP_TO_ISOLATION_BEGIN(lex->name.str, NULL, NULL) res= mysql_rm_db(thd, lex->name.str, lex->check_exists, 0); break; } @@ -3748,6 +4064,7 @@ end_with_restore_list: res= 1; break; } + WSREP_TO_ISOLATION_BEGIN(db->str, NULL, NULL) res= mysql_upgrade_db(thd, db); if (!res) my_ok(thd); @@ -3780,6 +4097,7 @@ end_with_restore_list: #endif if (check_access(thd, ALTER_ACL, db->str, NULL, NULL, 1, 0)) break; + WSREP_TO_ISOLATION_BEGIN(db->str, NULL, NULL) res= mysql_alter_db(thd, db->str, &create_info); break; } @@ -3812,6 +4130,7 @@ end_with_restore_list: if (res) break; + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) switch (lex->sql_command) { case SQLCOM_CREATE_EVENT: { @@ -3846,6 +4165,7 @@ end_with_restore_list: lex->spname->m_name); break; case SQLCOM_DROP_EVENT: + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) if (!(res= Events::drop_event(thd, lex->spname->m_db, lex->spname->m_name, lex->check_exists))) @@ -3860,6 +4180,7 @@ end_with_restore_list: if (check_access(thd, INSERT_ACL, "mysql", NULL, NULL, 1, 0)) break; #ifdef HAVE_DLOPEN + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) if (!(res = mysql_create_function(thd, &lex->udf))) my_ok(thd); #else @@ -3874,6 +4195,7 @@ end_with_restore_list: if (check_access(thd, INSERT_ACL, "mysql", NULL, NULL, 1, 1) && check_global_access(thd,CREATE_USER_ACL)) break; + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) /* Conditionally writes to binlog */ if (!(res= mysql_create_user(thd, lex->users_list))) my_ok(thd); @@ -3885,6 +4207,7 @@ end_with_restore_list: check_global_access(thd,CREATE_USER_ACL)) break; /* Conditionally writes to binlog */ + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) if (!(res= mysql_drop_user(thd, lex->users_list))) my_ok(thd); break; @@ -3895,6 +4218,7 @@ end_with_restore_list: check_global_access(thd,CREATE_USER_ACL)) break; /* Conditionally writes to binlog */ + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) if (!(res= mysql_rename_user(thd, lex->users_list))) my_ok(thd); break; @@ -3909,6 +4233,7 @@ end_with_restore_list: thd->binlog_invoker(); /* Conditionally writes to binlog */ + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) if (!(res = mysql_revoke_all(thd, lex->users_list))) my_ok(thd); break; @@ -3975,6 +4300,7 @@ end_with_restore_list: lex->type == TYPE_ENUM_PROCEDURE, 0)) goto error; /* Conditionally writes to binlog */ + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) res= mysql_routine_grant(thd, all_tables, lex->type == TYPE_ENUM_PROCEDURE, lex->users_list, grants, @@ -3988,6 +4314,7 @@ end_with_restore_list: all_tables, FALSE, UINT_MAX, FALSE)) goto error; /* Conditionally writes to binlog */ + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) res= mysql_table_grant(thd, all_tables, lex->users_list, lex->columns, lex->grant, lex->sql_command == SQLCOM_REVOKE); @@ -4003,6 +4330,7 @@ end_with_restore_list: } else { + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) /* Conditionally writes to binlog */ res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant, lex->sql_command == SQLCOM_REVOKE, @@ -4141,9 +4469,17 @@ end_with_restore_list: able to open it (with SQLCOM_HA_OPEN) in the first place. */ unit->set_limit(select_lex); +#ifdef WITH_WSREP + { char* tmp_info= NULL; + if (WSREP(thd)) tmp_info = (char *)thd_proc_info(thd, "mysql_ha_read()"); +#endif /* WITH_WSREP */ res= mysql_ha_read(thd, first_table, lex->ha_read_mode, lex->ident.str, lex->insert_list, lex->ha_rkey_mode, select_lex->where, unit->select_limit_cnt, unit->offset_limit_cnt); +#ifdef WITH_WSREP + if (WSREP(thd)) thd_proc_info(thd, tmp_info); + } +#endif /* WITH_WSREP */ break; case SQLCOM_BEGIN: @@ -4213,8 +4549,20 @@ end_with_restore_list: /* Disconnect the current client connection. */ if (tx_release) thd->killed= KILL_CONNECTION; - my_ok(thd); - break; + #ifdef WITH_WSREP + if (WSREP(thd)) { + if (thd->wsrep_conflict_state == NO_CONFLICT || + thd->wsrep_conflict_state == REPLAYING) + { + my_ok(thd); + } + } else { +#endif /* WITH_WSREP */ + my_ok(thd); + #ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ + break; } case SQLCOM_RELEASE_SAVEPOINT: if (trans_release_savepoint(thd, lex->ident)) @@ -4282,6 +4630,7 @@ end_with_restore_list: if (sp_process_definer(thd)) goto create_sp_error; + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) res= (sp_result= sp_create_routine(thd, lex->sphead->m_type, lex->sphead)); switch (sp_result) { case SP_OK: { @@ -4493,6 +4842,7 @@ create_sp_error: already puts on CREATE FUNCTION. */ /* Conditionally writes to binlog */ + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) sp_result= sp_update_routine(thd, type, lex->spname, &lex->sp_chistics); switch (sp_result) { @@ -4564,6 +4914,7 @@ create_sp_error: if (check_routine_access(thd, ALTER_PROC_ACL, db, name, lex->sql_command == SQLCOM_DROP_PROCEDURE, 0)) goto error; + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) /* Conditionally writes to binlog */ sp_result= sp_drop_routine(thd, type, lex->spname); @@ -4681,6 +5032,7 @@ create_sp_error: Note: SQLCOM_CREATE_VIEW also handles 'ALTER VIEW' commands as specified through the thd->lex->create_view_mode flag. */ + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) res= mysql_create_view(thd, first_table, thd->lex->create_view_mode); break; } @@ -4689,12 +5041,14 @@ create_sp_error: if (check_table_access(thd, DROP_ACL, all_tables, FALSE, UINT_MAX, FALSE)) goto error; /* Conditionally writes to binlog. */ + WSREP_TO_ISOLATION_BEGIN(NULL, NULL, NULL) res= mysql_drop_view(thd, first_table, thd->lex->drop_mode); break; } case SQLCOM_CREATE_TRIGGER: { /* Conditionally writes to binlog. */ + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) res= mysql_create_or_drop_trigger(thd, all_tables, 1); break; @@ -4702,6 +5056,7 @@ create_sp_error: case SQLCOM_DROP_TRIGGER: { /* Conditionally writes to binlog. */ + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) res= mysql_create_or_drop_trigger(thd, all_tables, 0); break; } @@ -4754,11 +5109,13 @@ create_sp_error: my_ok(thd); break; case SQLCOM_INSTALL_PLUGIN: + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) if (! (res= mysql_install_plugin(thd, &thd->lex->comment, &thd->lex->ident))) my_ok(thd); break; case SQLCOM_UNINSTALL_PLUGIN: + WSREP_TO_ISOLATION_BEGIN(WSREP_MYSQL_DB, NULL, NULL) if (! (res= mysql_uninstall_plugin(thd, &thd->lex->comment, &thd->lex->ident))) my_ok(thd); @@ -4919,6 +5276,9 @@ finish: /* Free tables */ THD_STAGE_INFO(thd, stage_closing_tables); close_thread_tables(thd); +#ifdef WITH_WSREP + thd->wsrep_consistency_check= NO_CONSISTENCY_CHECK; +#endif /* WITH_WSREP */ #ifndef DBUG_OFF if (lex->sql_command != SQLCOM_SET_OPTION && ! thd->in_sub_stmt) @@ -4959,6 +5319,7 @@ finish: { thd->mdl_context.release_statement_locks(); } + WSREP_TO_ISOLATION_END DBUG_RETURN(res || thd->is_error()); } @@ -5027,6 +5388,9 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables) if (!thd->get_sent_row_count()) status_var_increment(thd->status_var.empty_queries); status_var_add(thd->status_var.rows_sent, thd->get_sent_row_count()); +#ifdef WITH_WSREP + if (lex->sql_command == SQLCOM_SHOW_STATUS) wsrep_free_status(thd); +#endif /* WITH_WSREP */ return res; } @@ -5847,6 +6211,21 @@ void THD::reset_for_next_command(bool calculate_userstat) thd->auto_inc_intervals_in_cur_stmt_for_binlog.empty(); thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0; +#ifdef WITH_WSREP + if (WSREP(thd)) { + if (wsrep_auto_increment_control) + { + if (thd->variables.auto_increment_offset != + global_system_variables.auto_increment_offset) + thd->variables.auto_increment_offset= + global_system_variables.auto_increment_offset; + if (thd->variables.auto_increment_increment != + global_system_variables.auto_increment_increment) + thd->variables.auto_increment_increment= + global_system_variables.auto_increment_increment; + } + } +#endif /* WITH_WSREP */ thd->query_start_used= 0; thd->query_start_sec_part_used= 0; thd->is_fatal_error= thd->time_zone_used= 0; @@ -6056,6 +6435,179 @@ void mysql_init_multi_delete(LEX *lex) lex->query_tables_last= &lex->query_tables; } +#ifdef WITH_WSREP +void wsrep_replay_transaction(THD *thd) +{ + /* checking if BF trx must be replayed */ + if (thd->wsrep_conflict_state== MUST_REPLAY) + { + if (thd->wsrep_exec_mode!= REPL_RECV) + { + if (thd->stmt_da->is_sent) + { + WSREP_ERROR("replay issue, thd has reported status already"); + } + thd->stmt_da->reset_diagnostics_area(); + + thd->wsrep_conflict_state= REPLAYING; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + mysql_reset_thd_for_next_command(thd, opt_userstat_running); + thd->killed= NOT_KILLED; + close_thread_tables(thd); + if (thd->locked_tables_mode && thd->lock) + { + WSREP_DEBUG("releasing table lock for replaying (%ld)", + thd->thread_id); + thd->locked_tables_list.unlock_locked_tables(thd); + thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); + } + thd->mdl_context.release_transactional_locks(); + + thd_proc_info(thd, "wsrep replaying trx"); + WSREP_DEBUG("replay trx: %s %lld", + thd->query() ? thd->query() : "void", + (long long)thd->wsrep_trx_seqno); + struct wsrep_thd_shadow shadow; + wsrep_prepare_bf_thd(thd, &shadow); + int rcode = wsrep->replay_trx(wsrep, + &thd->wsrep_trx_handle, + (void *)thd); + + wsrep_return_from_bf_mode(thd, &shadow); + if (thd->wsrep_conflict_state!= REPLAYING) + WSREP_WARN("lost replaying mode: %d", thd->wsrep_conflict_state ); + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + + switch (rcode) + { + case WSREP_OK: + thd->wsrep_conflict_state= NO_CONFLICT; + wsrep->post_commit(wsrep, &thd->wsrep_trx_handle); + WSREP_DEBUG("trx_replay successful for: %ld %llu", + thd->thread_id, (long long)thd->real_id); + break; + case WSREP_TRX_FAIL: + if (thd->stmt_da->is_sent) + { + WSREP_ERROR("replay failed, thd has reported status"); + } + else + { + WSREP_DEBUG("replay failed, rolling back"); + my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); + } + thd->wsrep_conflict_state= ABORTED; + thd->wsrep_bf_thd = NULL; + wsrep->post_rollback(wsrep, &thd->wsrep_trx_handle); + break; + default: + WSREP_ERROR("trx_replay failed for: %d, query: %s", + rcode, thd->query() ? thd->query() : "void"); + /* we're now in inconsistent state, must abort */ + unireg_abort(1); + break; + } + mysql_mutex_lock(&LOCK_wsrep_replaying); + wsrep_replaying--; + WSREP_DEBUG("replaying decreased: %d, thd: %lu", + wsrep_replaying, thd->thread_id); + mysql_cond_broadcast(&COND_wsrep_replaying); + mysql_mutex_unlock(&LOCK_wsrep_replaying); + } + } +} + +static void wsrep_mysql_parse(THD *thd, char *rawbuf, uint length, + Parser_state *parser_state) +{ + bool is_autocommit= + !thd->in_multi_stmt_transaction_mode() && + thd->wsrep_conflict_state == NO_CONFLICT && + !thd->wsrep_applier && + wsrep_read_only_option(thd, thd->lex->query_tables); + + do + { + if (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT) + { + thd->wsrep_conflict_state= NO_CONFLICT; + } + mysql_parse(thd, rawbuf, length, parser_state); + + if (WSREP(thd)) { + /* wsrep BF abort in query exec phase */ + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state == MUST_ABORT) { + wsrep_client_rollback(thd); + + WSREP_DEBUG("abort in exec query state, avoiding autocommit"); + } + + if (thd->wsrep_conflict_state== MUST_REPLAY) + { + wsrep_replay_transaction(thd); + } + + /* setting error code for BF aborted trxs */ + if (thd->wsrep_conflict_state == ABORTED || + thd->wsrep_conflict_state == CERT_FAILURE) + { + mysql_reset_thd_for_next_command(thd, opt_userstat_running); + thd->killed= NOT_KILLED; + if (is_autocommit && + thd->lex->sql_command != SQLCOM_SELECT && + (thd->wsrep_retry_counter < thd->variables.wsrep_retry_autocommit)) + { + WSREP_DEBUG("wsrep retrying AC query: %s", + (thd->query()) ? thd->query() : "void"); + + close_thread_tables(thd); + + thd->wsrep_conflict_state= RETRY_AUTOCOMMIT; + thd->wsrep_retry_counter++; // grow + wsrep_copy_query(thd); + thd->set_time(); + parser_state->reset(rawbuf, length); + } + else + { + WSREP_DEBUG("%s, thd: %lu is_AC: %d, retry: %lu - %lu SQL: %s", + (thd->wsrep_conflict_state == ABORTED) ? + "BF Aborted" : "cert failure", + thd->thread_id, is_autocommit, thd->wsrep_retry_counter, + thd->variables.wsrep_retry_autocommit, thd->query()); + my_error(ER_LOCK_DEADLOCK, MYF(0), "wsrep aborted transaction"); + thd->killed= NOT_KILLED; + thd->wsrep_conflict_state= NO_CONFLICT; + if (thd->wsrep_conflict_state != REPLAYING) + thd->wsrep_retry_counter= 0; // reset + } + } + else + { + set_if_smaller(thd->wsrep_retry_counter, 0); // reset; eventually ok + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + } + } while (thd->wsrep_conflict_state== RETRY_AUTOCOMMIT); + + if (thd->wsrep_retry_query) + { + WSREP_DEBUG("releasing retry_query: conf %d sent %d kill %d errno %d SQL %s", + thd->wsrep_conflict_state, + thd->stmt_da->is_sent, + thd->killed, + thd->stmt_da->is_error() ? thd->stmt_da->sql_errno() : 0, + thd->wsrep_retry_query); + my_free(thd->wsrep_retry_query); + thd->wsrep_retry_query = NULL; + thd->wsrep_retry_query_len = 0; + thd->wsrep_retry_command = COM_CONNECT; + } +} +#endif /* WITH_WSREP */ /* When you modify mysql_parse(), you may need to mofify @@ -7063,8 +7615,14 @@ uint kill_one_thread(THD *thd, ulong id, killed_state kill_signal) faster and do a harder kill than KILL_SYSTEM_THREAD; */ +#ifdef WITH_WSREP + if (((thd->security_ctx->master_access & SUPER_ACL) || + thd->security_ctx->user_matches(tmp->security_ctx)) && + !wsrep_thd_is_brute_force((void *)tmp)) +#else if ((thd->security_ctx->master_access & SUPER_ACL) || thd->security_ctx->user_matches(tmp->security_ctx)) +#endif /* WITH_WSREP */ { tmp->awake(kill_signal); error=0; @@ -7839,6 +8397,586 @@ LEX_USER *create_definer(THD *thd, LEX_STRING *user_name, LEX_STRING *host_name) return definer; } +#ifdef WITH_WSREP +/* must have (&thd->LOCK_wsrep_thd) */ +static void wsrep_client_rollback(THD *thd) +{ + WSREP_DEBUG("client rollback due to BF abort for (%ld), query: %s", + thd->thread_id, thd->query()); + + thd->wsrep_conflict_state= ABORTING; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + trans_rollback(thd); + + if (thd->locked_tables_mode && thd->lock) + { + WSREP_DEBUG("unlocking tables for BF abort (%ld)", thd->thread_id); + thd->locked_tables_list.unlock_locked_tables(thd); + thd->variables.option_bits&= ~(OPTION_TABLE_LOCK); + } + + if (thd->global_read_lock.is_acquired()) + { + WSREP_DEBUG("unlocking GRL for BF abort (%ld)", thd->thread_id); + thd->global_read_lock.unlock_global_read_lock(thd); + } + + /* Release transactional metadata locks. */ + thd->mdl_context.release_transactional_locks(); + + if (thd->get_binlog_table_maps()) + { + WSREP_DEBUG("clearing binlog table map for BF abort (%ld)", thd->thread_id); + thd->clear_binlog_table_maps(); + } + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_conflict_state= ABORTED; + thd->wsrep_bf_thd = NULL; +} + +static enum wsrep_status wsrep_apply_sql( + THD *thd, const char *sql, size_t sql_len, time_t timeval, uint32 randseed) +{ + int error; + enum wsrep_status ret_code= WSREP_OK; + + DBUG_ENTER("wsrep_bf_execute_cb"); + thd->wsrep_exec_mode= REPL_RECV; + thd->net.vio= 0; + thd->start_time= timeval; + thd->wsrep_rand= randseed; + + thd->variables.option_bits |= OPTION_NOT_AUTOCOMMIT; + + DBUG_PRINT("wsrep", ("SQL: %s", sql)); + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_query_state= QUERY_EXEC; + /* preserve replaying mode */ + if (thd->wsrep_conflict_state!= REPLAYING) + thd->wsrep_conflict_state= NO_CONFLICT; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + if ((error= dispatch_command(COM_QUERY, thd, (char*)sql, sql_len))) { + WSREP_WARN("BF SQL apply failed: %d, %lld", + thd->wsrep_conflict_state, (long long)thd->wsrep_trx_seqno); + DBUG_RETURN(WSREP_FATAL); + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + if (thd->wsrep_conflict_state!= NO_CONFLICT && + thd->wsrep_conflict_state!= REPLAYING) { + ret_code= WSREP_FATAL; + WSREP_DEBUG("BF thd ending, with: %d, %lld", + thd->wsrep_conflict_state, (long long)thd->wsrep_trx_seqno); + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + assert(thd->wsrep_exec_mode== REPL_RECV); + DBUG_RETURN(ret_code); +} + +void wsrep_write_rbr_buf( + THD *thd, const void* rbr_buf, size_t buf_len) +{ + char filename[PATH_MAX]= {0}; + int len= snprintf(filename, PATH_MAX, "%s/GRA_%ld_%lld.log", + wsrep_data_home_dir, thd->thread_id, + (long long)thd->wsrep_trx_seqno); + if (len >= PATH_MAX) + { + WSREP_ERROR("RBR dump path too long: %d, skipping dump.", len); + return; + } + + FILE *of= fopen(filename, "wb"); + if (of) + { + fwrite (rbr_buf, buf_len, 1, of); + fclose(of); + } + else + { + WSREP_ERROR("Failed to open file '%s': %d (%s)", + filename, errno, strerror(errno)); + } +} + +static inline wsrep_status_t wsrep_apply_rbr( + THD *thd, const uchar *rbr_buf, size_t buf_len) +{ + char *buf= (char *)rbr_buf; + int rcode= 0; + int event= 1; + Format_description_log_event *description_event = wsrep_format_desc; + DBUG_ENTER("wsrep_apply_rbr"); + + if (thd->killed == KILL_CONNECTION) + { + WSREP_INFO("applier has been aborted, skipping apply_rbr: %lld", + (long long) thd->wsrep_trx_seqno); + DBUG_RETURN(WSREP_FATAL); + } + + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_query_state= QUERY_EXEC; + if (thd->wsrep_conflict_state!= REPLAYING) + thd->wsrep_conflict_state= NO_CONFLICT; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + if (!buf_len) WSREP_DEBUG("empty rbr buffer to apply: %lld", + (long long) thd->wsrep_trx_seqno); + + if ((rcode= trans_begin(thd))) + WSREP_WARN("begin for rbr apply failed: %lld, code: %d", + (long long) thd->wsrep_trx_seqno, rcode); + + while(buf_len) + { + int exec_res; + int error = 0; + Log_event* ev= wsrep_read_log_event(&buf, &buf_len, description_event); + + if (!ev) + { + WSREP_ERROR("applier could not read binlog event, seqno: %lld, len: %ld", + (long long)thd->wsrep_trx_seqno, buf_len); + rcode= 1; + goto error; + } + switch (ev->get_type_code()) { + case WRITE_ROWS_EVENT: + case UPDATE_ROWS_EVENT: + case DELETE_ROWS_EVENT: + DBUG_ASSERT(buf_len != 0 || + ((Rows_log_event *) ev)->get_flags(Rows_log_event::STMT_END_F)); + break; + case FORMAT_DESCRIPTION_EVENT: + description_event = (Format_description_log_event *)ev; + break; + default: + break; + } + + thd->variables.server_id = ev->server_id; // use the original server id for logging + thd->set_time(); // time the query + wsrep_xid_init(&thd->transaction.xid_state.xid, + wsrep_cluster_uuid(), + thd->wsrep_trx_seqno); + thd->lex->current_select= 0; + if (!ev->when) + ev->when = time(NULL); + ev->thd = thd; + exec_res = ev->apply_event(thd->wsrep_rli); + DBUG_PRINT("info", ("exec_event result: %d", exec_res)); + + if (exec_res) + { + WSREP_WARN("RBR event %d %s apply warning: %d, %lld", + event, ev->get_type_str(), exec_res, (long long) thd->wsrep_trx_seqno); + rcode= exec_res; + /* stop processing for the first error */ + delete ev; + goto error; + } + event++; + + if (thd->wsrep_conflict_state!= NO_CONFLICT && + thd->wsrep_conflict_state!= REPLAYING) + WSREP_WARN("conflict state after RBR event applying: %d, %lld", + thd->wsrep_query_state, (long long)thd->wsrep_trx_seqno); + + if (thd->wsrep_conflict_state == MUST_ABORT) { + WSREP_WARN("RBR event apply failed, rolling back: %lld", + (long long) thd->wsrep_trx_seqno); + trans_rollback(thd); + thd->locked_tables_list.unlock_locked_tables(thd); + /* Release transactional metadata locks. */ + thd->mdl_context.release_transactional_locks(); + thd->wsrep_conflict_state= NO_CONFLICT; + DBUG_RETURN(WSREP_FATAL); + } + + if (ev->get_type_code() != TABLE_MAP_EVENT && + ((Rows_log_event *) ev)->get_flags(Rows_log_event::STMT_END_F)) + { + // TODO: combine with commit on higher level common for the query ws + + thd->wsrep_rli->cleanup_context(thd, 0); + + if (error == 0) + { + thd->clear_error(); + } + else + WSREP_ERROR("Error in %s event: commit of row events failed: %lld", + ev->get_type_str(), (long long)thd->wsrep_trx_seqno); + } + + if (description_event != ev) + delete ev; + } + + error: + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + thd->wsrep_query_state= QUERY_IDLE; + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); + + assert(thd->wsrep_exec_mode== REPL_RECV); + + if (thd->killed == KILL_CONNECTION) + WSREP_INFO("applier aborted: %lld", (long long)thd->wsrep_trx_seqno); + + if (rcode) DBUG_RETURN(WSREP_FATAL); + DBUG_RETURN(WSREP_OK); +} + +wsrep_status_t wsrep_apply_cb(void* const ctx, + const void* const buf, size_t const buf_len, + wsrep_seqno_t const global_seqno) +{ + THD* const thd((THD*)ctx); + + thd->wsrep_trx_seqno= global_seqno; + +#ifdef WSREP_PROC_INFO + snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, + "applying write set %lld: %p, %zu", + (long long)thd->wsrep_trx_seqno, buf, buf_len); + thd_proc_info(thd, thd->wsrep_info); +#else + thd_proc_info(thd, "applying write set"); +#endif /* WSREP_PROC_INFO */ + + wsrep_status_t const rcode(wsrep_apply_rbr(thd, (const uchar*)buf, buf_len)); + +#ifdef WSREP_PROC_INFO + snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, + "applied write set %lld", (long long)thd->wsrep_trx_seqno); + thd_proc_info(thd, thd->wsrep_info); +#else + thd_proc_info(thd, "applied write set"); +#endif /* WSREP_PROC_INFO */ + + if (WSREP_OK != rcode) wsrep_write_rbr_buf(thd, buf, buf_len); + + return rcode; +} + +#if DELETE // this does not work in 5.5 +/* a common wrapper for end_trans() function - to put all necessary stuff */ +static inline wsrep_status_t +wsrep_end_trans (THD* const thd, enum enum_mysql_completiontype const end) +{ + if (0 == end_trans(thd, end)) + { + return WSREP_OK; + } + else + { + return WSREP_FATAL; + } +} +#endif + +wsrep_status_t wsrep_commit(THD* const thd, wsrep_seqno_t const global_seqno) +{ +#ifdef WSREP_PROC_INFO + snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, + "committing %lld", (long long)thd->wsrep_trx_seqno); + thd_proc_info(thd, thd->wsrep_info); +#else + thd_proc_info(thd, "committing"); +#endif /* WSREP_PROC_INFO */ + + wsrep_status_t const rcode(wsrep_apply_sql(thd, "COMMIT", 6, 0, 0)); +// wsrep_status_t const rcode(wsrep_end_trans (thd, COMMIT)); + +#ifdef WSREP_PROC_INFO + snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, + "committed %lld", (long long)thd->wsrep_trx_seqno); + thd_proc_info(thd, thd->wsrep_info); +#else + thd_proc_info(thd, "committed"); +#endif /* WSREP_PROC_INFO */ + + if (WSREP_OK == rcode) + { + // TODO: mark snapshot with global_seqno. + } + + return rcode; +} + +wsrep_status_t wsrep_rollback(THD* const thd, wsrep_seqno_t const global_seqno) +{ +#ifdef WSREP_PROC_INFO + snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, + "rolling back %lld", (long long)thd->wsrep_trx_seqno); + thd_proc_info(thd, thd->wsrep_info); +#else + thd_proc_info(thd, "rolling back"); +#endif /* WSREP_PROC_INFO */ + + wsrep_status_t const rcode(wsrep_apply_sql(thd, "ROLLBACK", 8, 0, 0)); +// wsrep_status_t const rcode(wsrep_end_trans (thd, ROLLBACK)); + +#ifdef WSREP_PROC_INFO + snprintf(thd->wsrep_info, sizeof(thd->wsrep_info) - 1, + "rolled back %lld", (long long)thd->wsrep_trx_seqno); + thd_proc_info(thd, thd->wsrep_info); +#else + thd_proc_info(thd, "rolled back"); +#endif /* WSREP_PROC_INFO */ + + return rcode; +} + +wsrep_status_t wsrep_commit_cb(void* const ctx, + wsrep_seqno_t const global_seqno, + bool const commit) +{ + THD* const thd((THD*)ctx); + + assert(global_seqno == thd->wsrep_trx_seqno); + + if (commit) + return wsrep_commit(thd, global_seqno); + else + return wsrep_rollback(thd, global_seqno); +} + +Relay_log_info* wsrep_relay_log_init(const char* log_fname) +{ + Relay_log_info* rli= new Relay_log_info(false); + + rli->no_storage= true; + if (!rli->relay_log.description_event_for_exec) + { + rli->relay_log.description_event_for_exec= + new Format_description_log_event(4); + } + + rli->sql_thd= current_thd; + return rli; +} + +void wsrep_prepare_bf_thd(THD *thd, struct wsrep_thd_shadow* shadow) +{ + shadow->options = thd->variables.option_bits; + shadow->wsrep_exec_mode = thd->wsrep_exec_mode; + shadow->vio = thd->net.vio; + + if (opt_log_slave_updates) + thd->variables.option_bits|= OPTION_BIN_LOG; + else + thd->variables.option_bits&= ~(OPTION_BIN_LOG); + + if (!thd->wsrep_rli) thd->wsrep_rli= wsrep_relay_log_init("wsrep_relay"); + + thd->wsrep_exec_mode= REPL_RECV; + thd->net.vio= 0; + thd->clear_error(); + + thd->variables.option_bits|= OPTION_NOT_AUTOCOMMIT; + + shadow->tx_isolation = thd->variables.tx_isolation; + thd->variables.tx_isolation = ISO_READ_COMMITTED; + thd->tx_isolation = ISO_READ_COMMITTED; +} + +void wsrep_return_from_bf_mode(THD *thd, struct wsrep_thd_shadow* shadow) +{ + thd->variables.option_bits = shadow->options; + thd->wsrep_exec_mode = shadow->wsrep_exec_mode; + thd->net.vio = shadow->vio; + thd->variables.tx_isolation = shadow->tx_isolation; +} + +void wsrep_replication_process(THD *thd) +{ + int rcode; + DBUG_ENTER("wsrep_replication_process"); + + struct wsrep_thd_shadow shadow; + wsrep_prepare_bf_thd(thd, &shadow); + + rcode = wsrep->recv(wsrep, (void *)thd); + DBUG_PRINT("wsrep",("wsrep_repl returned: %d", rcode)); + + WSREP_INFO("applier thread exiting (code:%d)", rcode); + + switch (rcode) { + case WSREP_OK: + case WSREP_NOT_IMPLEMENTED: + case WSREP_CONN_FAIL: + /* provider does not support slave operations / disconnected from group, + * just close applier thread */ + break; + case WSREP_NODE_FAIL: + /* data inconsistency => SST is needed */ + /* Note: we cannot just blindly restart replication here, + * SST might require server restart if storage engines must be + * initialized after SST */ + WSREP_ERROR("node consistency compromised, aborting"); + wsrep_kill_mysql(thd); + break; + case WSREP_WARNING: + case WSREP_TRX_FAIL: + case WSREP_TRX_MISSING: + /* these suggests a bug in provider code */ + WSREP_WARN("bad return from recv() call: %d", rcode); + /* fall through to node shutdown */ + case WSREP_FATAL: + /* Cluster connectivity is lost. + * + * If applier was killed on purpose (KILL_CONNECTION), we + * avoid mysql shutdown. This is because the killer will then handle + * shutdown processing (or replication restarting) + */ + if (thd->killed != KILL_CONNECTION) + { + wsrep_kill_mysql(thd); + } + break; + } + + if (thd->killed != KILL_CONNECTION) + { + mysql_mutex_lock(&LOCK_thread_count); + wsrep_close_applier(thd); + mysql_cond_broadcast(&COND_thread_count); + mysql_mutex_unlock(&LOCK_thread_count); + } + wsrep_return_from_bf_mode(thd, &shadow); + DBUG_VOID_RETURN; +} + +void wsrep_rollback_process(THD *thd) +{ + DBUG_ENTER("wsrep_rollback_process"); + + mysql_mutex_lock(&LOCK_wsrep_rollback); + wsrep_aborting_thd= NULL; + + while (thd->killed == NOT_KILLED) { + thd_proc_info(thd, "wsrep aborter idle"); + thd->mysys_var->current_mutex= &LOCK_wsrep_rollback; + thd->mysys_var->current_cond= &COND_wsrep_rollback; + + mysql_cond_wait(&COND_wsrep_rollback,&LOCK_wsrep_rollback); + + WSREP_DEBUG("WSREP rollback thread wakes for signal"); + + mysql_mutex_lock(&thd->mysys_var->mutex); + thd_proc_info(thd, "wsrep aborter active"); + thd->mysys_var->current_mutex= 0; + thd->mysys_var->current_cond= 0; + mysql_mutex_unlock(&thd->mysys_var->mutex); + + /* check for false alarms */ + if (!wsrep_aborting_thd) + { + WSREP_DEBUG("WSREP rollback thread has empty abort queue"); + } + /* process all entries in the queue */ + while (wsrep_aborting_thd) { + THD *aborting; + wsrep_aborting_thd_t next = wsrep_aborting_thd->next; + aborting = wsrep_aborting_thd->aborting_thd; + my_free(wsrep_aborting_thd); + wsrep_aborting_thd= next; + /* + * must release mutex, appliers my want to add more + * aborting thds in our work queue, while we rollback + */ + mysql_mutex_unlock(&LOCK_wsrep_rollback); + + mysql_mutex_lock(&aborting->LOCK_wsrep_thd); + if (aborting->wsrep_conflict_state== ABORTED) + { + WSREP_DEBUG("WSREP, thd already aborted: %llu state: %d", + (long long)aborting->real_id, + aborting->wsrep_conflict_state); + + mysql_mutex_unlock(&aborting->LOCK_wsrep_thd); + mysql_mutex_lock(&LOCK_wsrep_rollback); + continue; + } + aborting->wsrep_conflict_state= ABORTING; + + mysql_mutex_unlock(&aborting->LOCK_wsrep_thd); + + aborting->store_globals(); + + mysql_mutex_lock(&aborting->LOCK_wsrep_thd); + wsrep_client_rollback(aborting); + WSREP_DEBUG("WSREP rollbacker aborted thd: (%lu %llu)", + aborting->thread_id, (long long)aborting->real_id); + mysql_mutex_unlock(&aborting->LOCK_wsrep_thd); + + mysql_mutex_lock(&LOCK_wsrep_rollback); + } + } + + mysql_mutex_unlock(&LOCK_wsrep_rollback); + sql_print_information("WSREP: rollbacker thread exiting"); + + DBUG_PRINT("wsrep",("wsrep rollbacker thread exiting")); + DBUG_VOID_RETURN; +} +extern +int wsrep_thd_is_brute_force(void *thd_ptr) +{ + if (thd_ptr) { + switch (((THD *)thd_ptr)->wsrep_exec_mode) { + case LOCAL_STATE: + { + if (((THD *)thd_ptr)->wsrep_conflict_state== REPLAYING) + { + return 1; + } + return 0; + } + case REPL_RECV: return 1; + case TOTAL_ORDER: return 2; + case LOCAL_COMMIT: return 3; + } + } + return 0; +} +extern "C" +int wsrep_abort_thd(void *bf_thd_ptr, void *victim_thd_ptr, my_bool signal) +{ + THD *victim_thd = (THD *) victim_thd_ptr; + THD *bf_thd = (THD *) bf_thd_ptr; + DBUG_ENTER("wsrep_abort_thd"); + + if ( (WSREP(bf_thd) || + ( (WSREP_ON || wsrep_OSU_method_options == WSREP_OSU_RSU) && + bf_thd->wsrep_exec_mode == TOTAL_ORDER) ) && + victim_thd) + { + WSREP_DEBUG("wsrep_abort_thd, by: %llu, victim: %llu", (bf_thd) ? + (long long)bf_thd->real_id : 0, (long long)victim_thd->real_id); + ha_wsrep_abort_transaction(bf_thd, victim_thd, signal); + } + else + { + WSREP_DEBUG("wsrep_abort_thd not effective: %p %p", bf_thd, victim_thd); + } + + DBUG_RETURN(1); +} +extern "C" +int wsrep_thd_in_locking_session(void *thd_ptr) +{ + if (thd_ptr && ((THD *)thd_ptr)->in_lock_tables) { + return 1; + } + return 0; +} +#endif /** Retuns information about user or current user. diff --git a/sql/sql_parse.h b/sql/sql_parse.h index 346a3c8899b..7fc25b838ca 100644 --- a/sql/sql_parse.h +++ b/sql/sql_parse.h @@ -202,6 +202,22 @@ inline bool is_supported_parser_charset(CHARSET_INFO *cs) { return test(cs->mbminlen == 1); } +#ifdef WITH_WSREP + +#define WSREP_MYSQL_DB (char *)"mysql" +#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) \ + if (WSREP(thd) && wsrep_to_isolation_begin(thd, db_, table_, table_list_)) goto error; + +#define WSREP_TO_ISOLATION_END \ + if (WSREP(thd) || (thd && thd->wsrep_exec_mode==TOTAL_ORDER)) \ + wsrep_to_isolation_end(thd); + +#else + +#define WSREP_TO_ISOLATION_BEGIN(db_, table_, table_list_) +#define WSREP_TO_ISOLATION_END + +#endif /* WITH_WSREP */ #endif /* SQL_PARSE_INCLUDED */ diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 72f16ba7837..c0a547c46d8 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -3049,11 +3049,17 @@ void plugin_thdvar_init(THD *thd) thd->variables.dynamic_variables_size= 0; thd->variables.dynamic_variables_ptr= 0; +#ifdef WITH_WSREP + if (!WSREP(thd) || !thd->wsrep_applier) { +#endif mysql_mutex_lock(&LOCK_plugin); thd->variables.table_plugin= intern_plugin_lock(NULL, global_system_variables.table_plugin); intern_plugin_unlock(NULL, old_table_plugin); mysql_mutex_unlock(&LOCK_plugin); +#ifdef WITH_WSREP + } +#endif DBUG_VOID_RETURN; } diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 025ff8820e6..7ccc6aaad39 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -3490,7 +3490,9 @@ Prepared_statement::set_parameters(String *expanded_query, return res; } - +#ifdef WITH_WSREP +void wsrep_replay_transaction(THD *thd); +#endif /* WITH_WSREP */ /** Execute a prepared statement. Re-prepare it a limited number of times if necessary. @@ -3570,6 +3572,22 @@ reexecute: error= execute(expanded_query, open_cursor) || thd->is_error(); thd->m_reprepare_observer= NULL; +#ifdef WITH_WSREP + mysql_mutex_lock(&thd->LOCK_wsrep_thd); + switch (thd->wsrep_conflict_state) + { + case CERT_FAILURE: + WSREP_DEBUG("PS execute fail for CERT_FAILURE: thd: %ld err: %d", + thd->thread_id, thd->stmt_da->sql_errno() ); + thd->wsrep_conflict_state = NO_CONFLICT; + break; + + case MUST_REPLAY: + (void)wsrep_replay_transaction(thd); + default: break; + } + mysql_mutex_unlock(&thd->LOCK_wsrep_thd); +#endif /* WITH_WSREP */ if (error && !thd->is_fatal_error && !thd->killed && reprepare_observer.is_invalidated() && diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc index e9c9dc86e41..27156e2236a 100644 --- a/sql/sql_reload.cc +++ b/sql/sql_reload.cc @@ -253,7 +253,18 @@ bool reload_acl_and_cache(THD *thd, unsigned long options, } if (options & REFRESH_CHECKPOINT) disable_checkpoints(thd); - } +#ifdef WITH_WSREP + /* + We need to do it second time after wsrep appliers were blocked in + make_global_read_lock_block_commit(thd) above since they could have + modified the tables too. + */ + if (WSREP(thd) && + close_cached_tables(thd, tables, (options & REFRESH_FAST) ? + FALSE : TRUE, TRUE)) + result= 1; +#endif /* WITH_WSREP */ + } else { if (thd && thd->locked_tables_mode) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index ba36c0fc63f..feba387d3b4 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -8614,7 +8614,8 @@ ST_FIELD_INFO variables_fields_info[]= { {"VARIABLE_NAME", 64, MYSQL_TYPE_STRING, 0, 0, "Variable_name", SKIP_OPEN_TABLE}, - {"VARIABLE_VALUE", 1024, MYSQL_TYPE_STRING, 0, 1, "Value", SKIP_OPEN_TABLE}, + {"VARIABLE_VALUE", MYSQL_MAX_VARIABLE_VALUE_LEN, MYSQL_TYPE_STRING, 0, 1, + "Value", SKIP_OPEN_TABLE}, {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE} }; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 60fd630001a..6bb650f55db 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6621,6 +6621,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, } } +#ifdef WITH_WSREP + bool do_log_write(true); +#endif /* WITH_WSREP */ if (error == HA_ERR_WRONG_COMMAND) { error= 0; @@ -6628,6 +6631,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), table->file->table_type(), table->s->db.str, table->s->table_name.str); +#ifdef WITH_WSREP + WSREP_DEBUG("ignoring DDL failure: %d %s", error, thd->query()); +#endif /* WITH_WSREP */ } if (!error) diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 35a4464b9e2..c23543bd9f3 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -2452,3 +2452,55 @@ bool load_table_name_for_trigger(THD *thd, DBUG_RETURN(FALSE); } +#ifdef WITH_WSREP +int wsrep_create_trigger_query(THD *thd, uchar** buf, uint* buf_len) +{ + LEX *lex= thd->lex; + String stmt_query; + + LEX_STRING definer_user; + LEX_STRING definer_host; + + if (!lex->definer) + { + if (!thd->slave_thread) + { + if (!(lex->definer= create_default_definer(thd))) + return 1; + } + } + + if (lex->definer) + { + /* SUID trigger. */ + + definer_user= lex->definer->user; + definer_host= lex->definer->host; + } + else + { + /* non-SUID trigger. */ + + definer_user.str= 0; + definer_user.length= 0; + + definer_host.str= 0; + definer_host.length= 0; + } + + stmt_query.append(STRING_WITH_LEN("CREATE ")); + + append_definer(thd, &stmt_query, &definer_user, &definer_host); + + LEX_STRING stmt_definition; + stmt_definition.str= (char*) thd->lex->stmt_definition_begin; + stmt_definition.length= thd->lex->stmt_definition_end + - thd->lex->stmt_definition_begin; + trim_whitespace(thd->charset(), & stmt_definition); + + stmt_query.append(stmt_definition.str, stmt_definition.length); + + return wsrep_to_buf_helper(thd, stmt_query.c_ptr(), stmt_query.length(), + buf, buf_len); +} +#endif /* WITH_WSREP */ diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index 19ce553f5ce..83cc0ed2cea 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -24,6 +24,9 @@ #include "sql_acl.h" // DROP_ACL #include "sql_parse.h" // check_one_table_access() #include "sql_truncate.h" +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" +#endif /* WITH_WSREP */ #include "sql_show.h" //append_identifier() @@ -531,9 +534,14 @@ bool Truncate_statement::execute(THD *thd) if (check_one_table_access(thd, DROP_ACL, first_table)) DBUG_RETURN(res); +#ifdef WITH_WSREP + if (WSREP(thd) && wsrep_to_isolation_begin(thd, + first_table->db, + first_table->table_name, NULL)) + DBUG_RETURN(TRUE); +#endif /* WITH_WSREP */ if (! (res= truncate_table(thd, first_table))) my_ok(thd); - DBUG_RETURN(res); } diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 8413f612111..137acc6b52b 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -904,7 +904,11 @@ int mysql_update(THD *thd, */ if ((error < 0) || thd->transaction.stmt.modified_non_trans_table) { +#ifdef WITH_WSREP + if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) +#else if (mysql_bin_log.is_open()) +#endif { int errcode= 0; if (error < 0) @@ -2044,7 +2048,11 @@ void multi_update::abort_result_set() The query has to binlog because there's a modified non-transactional table either from the query's list or via a stored routine: bug#13270,23333 */ +#ifdef WITH_WSREP + if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) +#else if (mysql_bin_log.is_open()) +#endif { /* THD::killed status might not have been set ON at time of an error @@ -2313,7 +2321,11 @@ bool multi_update::send_eof() if (local_error == 0 || thd->transaction.stmt.modified_non_trans_table) { +#ifdef WITH_WSREP + if (WSREP_EMULATE_BINLOG(thd) || mysql_bin_log.is_open()) +#else if (mysql_bin_log.is_open()) +#endif { int errcode= 0; if (local_error == 0) diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 0b543b8218a..9ca504fd275 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -4042,6 +4042,226 @@ static Sys_var_tz Sys_time_zone( "time_zone", "time_zone", SESSION_VAR(time_zone), NO_CMD_LINE, DEFAULT(&default_tz), NO_MUTEX_GUARD, IN_BINLOG); +#ifdef WITH_WSREP +#include "wsrep_mysqld.h" + +static Sys_var_charptr Sys_wsrep_provider( + "wsrep_provider", "Path to replication provider library", + PREALLOCATED GLOBAL_VAR(wsrep_provider), CMD_LINE(REQUIRED_ARG, OPT_WSREP_PROVIDER), + IN_FS_CHARSET, DEFAULT(wsrep_provider), + // IN_FS_CHARSET, DEFAULT(wsrep_provider_default), + NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(wsrep_provider_check), ON_UPDATE(wsrep_provider_update)); + +static Sys_var_charptr Sys_wsrep_provider_options( + "wsrep_provider_options", "provider specific options", + PREALLOCATED GLOBAL_VAR(wsrep_provider_options), + CMD_LINE(REQUIRED_ARG, OPT_WSREP_PROVIDER_OPTIONS), + IN_FS_CHARSET, DEFAULT(wsrep_provider_options), + NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(wsrep_provider_options_check), + ON_UPDATE(wsrep_provider_options_update)); + +static Sys_var_charptr Sys_wsrep_data_home_dir( + "wsrep_data_home_dir", "home directory for wsrep provider", + READ_ONLY GLOBAL_VAR(wsrep_data_home_dir), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(""), + NO_MUTEX_GUARD, NOT_IN_BINLOG); + +static Sys_var_charptr Sys_wsrep_cluster_name( + "wsrep_cluster_name", "Name for the cluster", + GLOBAL_VAR(wsrep_cluster_name), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(wsrep_cluster_name), + NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(wsrep_cluster_name_check), + ON_UPDATE(wsrep_cluster_name_update)); + +static PolyLock_mutex PLock_wsrep_slave_threads(&LOCK_wsrep_slave_threads); +static Sys_var_charptr Sys_wsrep_cluster_address ( + "wsrep_cluster_address", "Address to initially connect to cluster", + PREALLOCATED GLOBAL_VAR(wsrep_cluster_address), + CMD_LINE(REQUIRED_ARG, OPT_WSREP_CLUSTER_ADDRESS), + IN_FS_CHARSET, DEFAULT(wsrep_cluster_address), + &PLock_wsrep_slave_threads, NOT_IN_BINLOG, + ON_CHECK(wsrep_cluster_address_check), + ON_UPDATE(wsrep_cluster_address_update)); + +static Sys_var_charptr Sys_wsrep_node_name ( + "wsrep_node_name", "Node name", + GLOBAL_VAR(wsrep_node_name), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(wsrep_node_name), + NO_MUTEX_GUARD, NOT_IN_BINLOG); + +static Sys_var_charptr Sys_wsrep_node_address ( + "wsrep_node_address", "Node address", + GLOBAL_VAR(wsrep_node_address), CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(wsrep_node_address), + NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(wsrep_node_address_check), + ON_UPDATE(wsrep_node_address_update)); + +static Sys_var_charptr Sys_wsrep_node_incoming_address( + "wsrep_node_incoming_address", "Client connection address", + GLOBAL_VAR(wsrep_node_incoming_address),CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(wsrep_node_incoming_address), + NO_MUTEX_GUARD, NOT_IN_BINLOG); + +static Sys_var_ulong Sys_wsrep_slave_threads( + "wsrep_slave_threads", "Number of slave appliers to launch", + GLOBAL_VAR(wsrep_slave_threads), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, 512), DEFAULT(1), BLOCK_SIZE(1), + &PLock_wsrep_slave_threads, NOT_IN_BINLOG, + ON_CHECK(wsrep_slave_threads_check), + ON_UPDATE(wsrep_slave_threads_update)); + +static Sys_var_charptr Sys_wsrep_dbug_option( + "wsrep_dbug_option", "DBUG options to provider library", + GLOBAL_VAR(wsrep_dbug_option),CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(""), + NO_MUTEX_GUARD, NOT_IN_BINLOG); + +static Sys_var_mybool Sys_wsrep_debug( + "wsrep_debug", "To enable debug level logging", + GLOBAL_VAR(wsrep_debug), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_mybool Sys_wsrep_convert_LOCK_to_trx( + "wsrep_convert_LOCK_to_trx", "To convert locking sessions " + "into transactions", + GLOBAL_VAR(wsrep_convert_LOCK_to_trx), + CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_ulong Sys_wsrep_retry_autocommit( + "wsrep_retry_autocommit", "Max number of times to retry " + "a failed autocommit statement", + SESSION_VAR(wsrep_retry_autocommit), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, 10000), DEFAULT(1), BLOCK_SIZE(1)); + +static Sys_var_mybool Sys_wsrep_auto_increment_control( + "wsrep_auto_increment_control", "To automatically control the " + "assignment of autoincrement variables", + GLOBAL_VAR(wsrep_auto_increment_control), + CMD_LINE(OPT_ARG), DEFAULT(TRUE)); + +static Sys_var_mybool Sys_wsrep_drupal_282555_workaround( + "wsrep_drupal_282555_workaround", "To use a workaround for" + "bad autoincrement value", + GLOBAL_VAR(wsrep_drupal_282555_workaround), + CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_charptr sys_wsrep_sst_method( + "wsrep_sst_method", "State snapshot transfer method", + GLOBAL_VAR(wsrep_sst_method),CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(wsrep_sst_method), NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(wsrep_sst_method_check), + ON_UPDATE(wsrep_sst_method_update)); + +static Sys_var_charptr Sys_wsrep_sst_receive_address( + "wsrep_sst_receive_address", "Address where node is waiting for " + "SST contact", + GLOBAL_VAR(wsrep_sst_receive_address),CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(wsrep_sst_receive_address), NO_MUTEX_GUARD, + NOT_IN_BINLOG, + ON_CHECK(wsrep_sst_receive_address_check), + ON_UPDATE(wsrep_sst_receive_address_update)); + +static Sys_var_charptr Sys_wsrep_sst_auth( + "wsrep_sst_auth", "Authentication for SST connection", + PREALLOCATED GLOBAL_VAR(wsrep_sst_auth), CMD_LINE(REQUIRED_ARG, OPT_WSREP_SST_AUTH), + IN_FS_CHARSET, DEFAULT(wsrep_sst_auth), NO_MUTEX_GUARD, + NOT_IN_BINLOG, + ON_CHECK(wsrep_sst_auth_check), + ON_UPDATE(wsrep_sst_auth_update)); + +static Sys_var_charptr Sys_wsrep_sst_donor( + "wsrep_sst_donor", "preferred donor node for the SST", + GLOBAL_VAR(wsrep_sst_donor),CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(wsrep_sst_donor_check), + ON_UPDATE(wsrep_sst_donor_update)); + +static Sys_var_mybool Sys_wsrep_sst_donor_rejects_queries( + "wsrep_sst_donor_rejects_queries", "Reject client queries " + "when donating state snapshot transfer", + GLOBAL_VAR(wsrep_sst_donor_rejects_queries), + CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_mybool Sys_wsrep_on ( + "wsrep_on", "To enable wsrep replication ", + SESSION_VAR(wsrep_on), + CMD_LINE(OPT_ARG), DEFAULT(TRUE), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(wsrep_on_update)); + +static Sys_var_charptr Sys_wsrep_start_position ( + "wsrep_start_position", "global transaction position to start from ", + GLOBAL_VAR(wsrep_start_position), + CMD_LINE(REQUIRED_ARG, OPT_WSREP_START_POSITION), + IN_FS_CHARSET, DEFAULT(wsrep_start_position), + NO_MUTEX_GUARD, NOT_IN_BINLOG, + ON_CHECK(wsrep_start_position_check), + ON_UPDATE(wsrep_start_position_update)); + +static Sys_var_ulonglong Sys_wsrep_max_ws_size ( + "wsrep_max_ws_size", "Max write set size (bytes)", + GLOBAL_VAR(wsrep_max_ws_size), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1024, 4294967296ULL), DEFAULT(1073741824ULL), BLOCK_SIZE(1)); + +static Sys_var_ulong Sys_wsrep_max_ws_rows ( + "wsrep_max_ws_rows", "Max number of rows in write set", + GLOBAL_VAR(wsrep_max_ws_rows), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(1, 1048576), DEFAULT(131072), BLOCK_SIZE(1)); + +static Sys_var_charptr Sys_wsrep_notify_cmd( + "wsrep_notify_cmd", "", + GLOBAL_VAR(wsrep_notify_cmd),CMD_LINE(REQUIRED_ARG), + IN_FS_CHARSET, DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG); + +static Sys_var_mybool Sys_wsrep_certify_nonPK( + "wsrep_certify_nonPK", "Certify tables with no primary key", + GLOBAL_VAR(wsrep_certify_nonPK), + CMD_LINE(OPT_ARG), DEFAULT(TRUE)); + +static Sys_var_mybool Sys_wsrep_causal_reads( + "wsrep_causal_reads", "Enable \"strictly synchronous\" semantics for read operations", + SESSION_VAR(wsrep_causal_reads), + CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + // ON_UPDATE(wsrep_causal_reads_update)); + +static const char *wsrep_OSU_method_names[]= { "TOI", "RSU", NullS }; +static Sys_var_enum Sys_wsrep_OSU_method( + "wsrep_OSU_method", "Method for Online Schema Upgrade", + GLOBAL_VAR(wsrep_OSU_method_options), CMD_LINE(OPT_ARG), + wsrep_OSU_method_names, DEFAULT(WSREP_OSU_TOI), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(0)); + +static Sys_var_enum Sys_wsrep_forced_binlog_format( + "wsrep_forced_binlog_format", "binlog format to take effect over user's choice", + GLOBAL_VAR(wsrep_forced_binlog_format), + CMD_LINE(REQUIRED_ARG, OPT_BINLOG_FORMAT), + wsrep_binlog_format_names, DEFAULT(BINLOG_FORMAT_UNSPEC), + NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), + ON_UPDATE(0)); + +static Sys_var_mybool Sys_wsrep_recover_datadir( + "wsrep_recover", "Recover database state after crash and exit", + READ_ONLY GLOBAL_VAR(wsrep_recovery), + CMD_LINE(OPT_ARG, OPT_WSREP_RECOVER), DEFAULT(FALSE)); + +static Sys_var_mybool Sys_wsrep_replicate_myisam( + "wsrep_replicate_myisam", "To enable myisam replication", + GLOBAL_VAR(wsrep_replicate_myisam), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_mybool Sys_wsrep_log_conflicts( + "wsrep_log_conflicts", "To log multi-master conflicts", + GLOBAL_VAR(wsrep_log_conflicts), CMD_LINE(OPT_ARG), DEFAULT(FALSE)); + +static Sys_var_ulong Sys_wsrep_mysql_replication_bundle( + "wsrep_mysql_replication_bundle", "mysql replication group commit ", + GLOBAL_VAR(wsrep_mysql_replication_bundle), CMD_LINE(REQUIRED_ARG), + VALID_RANGE(0, 1000), DEFAULT(0), BLOCK_SIZE(1)); + +#endif /* WITH_WSREP */ static Sys_var_charptr Sys_ignore_db_dirs( "ignore_db_dirs", diff --git a/sql/transaction.cc b/sql/transaction.cc index 9a1952427d8..a381b5d21ce 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -97,6 +97,9 @@ static bool xa_trans_force_rollback(THD *thd) by ha_rollback()/THD::transaction::cleanup(). */ thd->transaction.xid_state.rm_error= 0; +#ifdef WITH_WSREP + wsrep_register_hton(thd, TRUE); +#endif /* WITH_WSREP */ if (ha_rollback_trans(thd, true)) { my_error(ER_XAER_RMERR, MYF(0)); @@ -135,6 +138,9 @@ bool trans_begin(THD *thd, uint flags) (thd->variables.option_bits & OPTION_TABLE_LOCK)) { thd->variables.option_bits&= ~OPTION_TABLE_LOCK; +#ifdef WITH_WSREP + wsrep_register_hton(thd, TRUE); +#endif /* WITH_WSREP */ thd->server_status&= ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); @@ -176,6 +182,12 @@ bool trans_begin(THD *thd, uint flags) thd->tx_read_only= false; } +#ifdef WITH_WSREP + thd->wsrep_PA_safe= true; + if (WSREP_CLIENT(thd) && wsrep_causal_wait(thd)) + DBUG_RETURN(TRUE); +#endif /* WITH_WSREP */ + thd->variables.option_bits|= OPTION_BEGIN; thd->server_status|= SERVER_STATUS_IN_TRANS; if (thd->tx_read_only) @@ -207,6 +219,9 @@ bool trans_commit(THD *thd) if (trans_check(thd)) DBUG_RETURN(TRUE); +#ifdef WITH_WSREP + wsrep_register_hton(thd, TRUE); +#endif /* WITH_WSREP */ thd->server_status&= ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); @@ -252,6 +267,9 @@ bool trans_commit_implicit(THD *thd) /* Safety if one did "drop table" on locked tables */ if (!thd->locked_tables_mode) thd->variables.option_bits&= ~OPTION_TABLE_LOCK; +#ifdef WITH_WSREP + wsrep_register_hton(thd, TRUE); +#endif /* WITH_WSREP */ thd->server_status&= ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); @@ -288,9 +306,15 @@ bool trans_rollback(THD *thd) int res; DBUG_ENTER("trans_rollback"); +#ifdef WITH_WSREP + thd->wsrep_PA_safe= true; +#endif /* WITH_WSREP */ if (trans_check(thd)) DBUG_RETURN(TRUE); +#ifdef WITH_WSREP + wsrep_register_hton(thd, TRUE); +#endif /* WITH_WSREP */ thd->server_status&= ~(SERVER_STATUS_IN_TRANS | SERVER_STATUS_IN_TRANS_READONLY); DBUG_PRINT("info", ("clearing SERVER_STATUS_IN_TRANS")); @@ -333,6 +357,9 @@ bool trans_commit_stmt(THD *thd) if (thd->transaction.stmt.ha_list) { +#ifdef WITH_WSREP + wsrep_register_hton(thd, FALSE); +#endif /* WITH_WSREP */ res= ha_commit_trans(thd, FALSE); if (! thd->in_active_multi_stmt_transaction()) { @@ -378,9 +405,19 @@ bool trans_rollback_stmt(THD *thd) if (thd->transaction.stmt.ha_list) { +#ifdef WITH_WSREP + wsrep_register_hton(thd, FALSE); +#endif /* WITH_WSREP */ ha_rollback_trans(thd, FALSE); if (thd->transaction_rollback_request && !thd->in_sub_stmt) +#ifdef WITH_WSREP + { + wsrep_register_hton(thd, TRUE); +#endif /* WITH_WSREP */ ha_rollback_trans(thd, TRUE); +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ if (! thd->in_active_multi_stmt_transaction()) { thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation; @@ -738,6 +775,9 @@ bool trans_xa_commit(THD *thd) } else if (xa_state == XA_IDLE && thd->lex->xa_opt == XA_ONE_PHASE) { +#ifdef WITH_WSREP + wsrep_register_hton(thd, TRUE); +#endif /* WITH_WSREP */ int r= ha_commit_trans(thd, TRUE); if ((res= test(r))) my_error(r == 1 ? ER_XA_RBROLLBACK : ER_XAER_RMERR, MYF(0)); @@ -759,6 +799,9 @@ bool trans_xa_commit(THD *thd) if (thd->mdl_context.acquire_lock(&mdl_request, thd->variables.lock_wait_timeout)) { +#ifdef WITH_WSREP + wsrep_register_hton(thd, TRUE); +#endif /* WITH_WSREP */ ha_rollback_trans(thd, TRUE); my_error(ER_XAER_RMERR, MYF(0)); } diff --git a/storage/innobase/dict/dict0dict.cc b/storage/innobase/dict/dict0dict.cc index 8282dafda0c..663fee59d87 100644 --- a/storage/innobase/dict/dict0dict.cc +++ b/storage/innobase/dict/dict0dict.cc @@ -3062,7 +3062,26 @@ next_rec: return(NULL); } - +#ifdef WITH_WSREP +dict_index_t* +wsrep_dict_foreign_find_index( +/*====================*/ + dict_table_t* table, /*!< in: table */ + const char** columns,/*!< in: array of column names */ + ulint n_cols, /*!< in: number of columns */ + dict_index_t* types_idx, /*!< in: NULL or an index to whose types the + column types must match */ + ibool check_charsets, + /*!< in: whether to check charsets. + only has an effect if types_idx != NULL */ + ulint check_null) + /*!< in: nonzero if none of the columns must + be declared NOT NULL */ +{ + return dict_foreign_find_index( + table, columns, n_cols, types_idx, check_charsets, check_null); +} +#endif /* WITH_WSREP */ /**********************************************************************//** Find an index that is equivalent to the one passed in and is not marked for deletion. diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index a6fdaf36d32..7209b8bc42d 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -78,12 +78,18 @@ this program; if not, write to the Free Software Foundation, Inc., #include "ha_prototypes.h" #include "ut0mem.h" #include "ibuf0ibuf.h" +#ifdef WITH_WSREP +#include "../storage/innobase/include/ut0byte.h" +#endif /* WITH_WSREP */ #include "dict0dict.h" #include "srv0mon.h" #include "pars0pars.h" #include "fts0fts.h" #include "fts0types.h" +#ifdef WITH_WSREP +#include "dict0priv.h" +#endif /* WITH_WSREP */ #include "ha_innodb.h" #include "i_s.h" @@ -91,6 +97,32 @@ this program; if not, write to the Free Software Foundation, Inc., # define MYSQL_PLUGIN_IMPORT /* nothing */ # endif /* MYSQL_PLUGIN_IMPORT */ +#ifdef WITH_WSREP +#include <wsrep_mysqld.h> +#include <my_md5.h> +extern my_bool wsrep_certify_nonPK; +class binlog_trx_data; +extern handlerton *binlog_hton; + +extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log; +extern MYSQL_PLUGIN_IMPORT mysql_mutex_t LOCK_wsrep_rollback; +extern MYSQL_PLUGIN_IMPORT mysql_cond_t COND_wsrep_rollback; +extern MYSQL_PLUGIN_IMPORT wsrep_aborting_thd_t wsrep_aborting_thd; + +static inline wsrep_trx_handle_t* +wsrep_trx_handle(THD* thd, const trx_t* trx) { + return wsrep_trx_handle_for_id(wsrep_thd_trx_handle(thd), + (wsrep_trx_id_t)trx->id); +} + +extern bool wsrep_prepare_key_for_innodb(const uchar *cache_key, + size_t cache_key_len, + const uchar* row_id, + size_t row_id_len, + wsrep_key_part_t* key, + size_t* key_len); + +#endif /* WITH_WSREP */ /** to protect innobase_open_files */ static mysql_mutex_t innobase_share_mutex; /** to force correct commit order in binlog */ @@ -1206,6 +1238,15 @@ thd_to_trx( { return(*(trx_t**) thd_ha_data(thd, innodb_hton_ptr)); } +#ifdef WITH_WSREP +ulonglong +thd_to_trx_id( +/*=======*/ + THD* thd) /*!< in: MySQL thread */ +{ + return(thd_to_trx(thd)->id); +} +#endif /********************************************************************//** Call this function when mysqld passes control to the client. That is to @@ -1235,6 +1276,15 @@ innobase_release_temporary_latches( return(0); } +#ifdef WITH_WSREP +static int +wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, + my_bool signal); +static void +wsrep_fake_trx_id(handlerton* hton, THD *thd); +static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid); +static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid); +#endif /********************************************************************//** Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth time calls srv_active_wake_master_thread. This function should be used @@ -1643,6 +1693,9 @@ int innobase_mysql_tmpfile(void) /*========================*/ { +#ifdef WITH_INNODB_DISALLOW_WRITES + os_event_wait(srv_allow_writes_event); +#endif /* WITH_INNODB_DISALLOW_WRITES */ int fd2 = -1; File fd; @@ -2624,6 +2677,12 @@ innobase_init( innobase_release_temporary_latches; innobase_hton->alter_table_flags = innobase_alter_table_flags; +#ifdef WITH_WSREP + innobase_hton->wsrep_abort_transaction=wsrep_abort_transaction; + innobase_hton->wsrep_set_checkpoint=innobase_wsrep_set_checkpoint; + innobase_hton->wsrep_get_checkpoint=innobase_wsrep_get_checkpoint; + innobase_hton->wsrep_fake_trx_id=wsrep_fake_trx_id; +#endif /* WITH_WSREP */ innobase_hton->kill_query = innobase_kill_query; if (srv_file_per_table) @@ -3178,6 +3237,27 @@ innobase_commit_low( trx_commit_for_mysql(trx); } +#ifdef WITH_WSREP + THD* thd = (THD*)trx->mysql_thd; + const char* tmp = 0; + if (wsrep_on((void*)thd)) { +#ifdef WSREP_PROC_INFO + char info[64]; + info[sizeof(info) - 1] = '\0'; + snprintf(info, sizeof(info) - 1, + "innobase_commit_low():trx_commit_for_mysql(%lld)", + (long long) wsrep_thd_trx_seqno(thd)); + tmp = thd_proc_info(thd, info); + +#else + tmp = thd_proc_info(thd, "innobase_commit_low()"); +#endif /* WSREP_PROC_INFO */ + } +#endif /* WITH_WSREP */ + trx_commit_for_mysql(trx); +#ifdef WITH_WSREP + if (wsrep_on((void*)thd)) { thd_proc_info(thd, tmp); } +#endif /* WITH_WSREP */ } /*****************************************************************//** @@ -3991,7 +4071,11 @@ ha_innobase::max_supported_key_length() const case 8192: return(1536); default: +#ifdef WITH_WSREP return(3500); +#else + return(3500); +#endif } } @@ -4956,7 +5040,96 @@ get_field_offset( { return((uint) (field->ptr - table->record[0])); } +#ifdef WITH_WSREP +UNIV_INTERN +void +wsrep_innobase_mysql_sort( +/*===============*/ + /* out: str contains sort string */ + int mysql_type, /* in: MySQL type */ + uint charset_number, /* in: number of the charset */ + unsigned char* str, /* in: data field */ + unsigned int str_length) /* in: data field length, + not UNIV_SQL_NULL */ +{ + CHARSET_INFO* charset; + enum_field_types mysql_tp; + + DBUG_ASSERT(str_length != UNIV_SQL_NULL); + + mysql_tp = (enum_field_types) mysql_type; + + switch (mysql_tp) { + + case MYSQL_TYPE_BIT: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_VARCHAR: + { + uchar tmp_str[REC_VERSION_56_MAX_INDEX_COL_LEN]; + uint tmp_length = REC_VERSION_56_MAX_INDEX_COL_LEN; + + /* Use the charset number to pick the right charset struct for + the comparison. Since the MySQL function get_charset may be + slow before Bar removes the mutex operation there, we first + look at 2 common charsets directly. */ + + if (charset_number == default_charset_info->number) { + charset = default_charset_info; + } else if (charset_number == my_charset_latin1.number) { + charset = &my_charset_latin1; + } else { + charset = get_charset(charset_number, MYF(MY_WME)); + + if (charset == NULL) { + sql_print_error("InnoDB needs charset %lu for doing " + "a comparison, but MySQL cannot " + "find that charset.", + (ulong) charset_number); + ut_a(0); + } + } + + ut_a(str_length <= tmp_length); + memcpy(tmp_str, str, str_length); + tmp_length = charset->coll->strnxfrm(charset, str, str_length, + tmp_str, str_length); + DBUG_ASSERT(tmp_length == str_length); + + break; + } + case MYSQL_TYPE_DECIMAL : + case MYSQL_TYPE_TINY : + case MYSQL_TYPE_SHORT : + case MYSQL_TYPE_LONG : + case MYSQL_TYPE_FLOAT : + case MYSQL_TYPE_DOUBLE : + case MYSQL_TYPE_NULL : + case MYSQL_TYPE_TIMESTAMP : + case MYSQL_TYPE_LONGLONG : + case MYSQL_TYPE_INT24 : + case MYSQL_TYPE_DATE : + case MYSQL_TYPE_TIME : + case MYSQL_TYPE_DATETIME : + case MYSQL_TYPE_YEAR : + case MYSQL_TYPE_NEWDATE : + case MYSQL_TYPE_NEWDECIMAL : + case MYSQL_TYPE_ENUM : + case MYSQL_TYPE_SET : + case MYSQL_TYPE_GEOMETRY : + break; + default: + break; + } + + return; +} +#endif // WITH_WSREP /**************************************************************//** Checks if a field in a record is SQL NULL. Uses the record format information in table to track the null bit in record. @@ -5481,6 +5654,264 @@ innobase_read_from_2_little_endian( /*******************************************************************//** Stores a key value for a row to a buffer. @return key value length as stored in buff */ +#ifdef WITH_WSREP +UNIV_INTERN +uint +wsrep_store_key_val_for_row( +/*===============================*/ + TABLE* table, + uint keynr, /*!< in: key number */ + char* buff, /*!< in/out: buffer for the key value (in MySQL + format) */ + uint buff_len,/*!< in: buffer length */ + const uchar* record, + ibool* key_is_null)/*!< out: full key was null */ +{ + KEY* key_info = table->key_info + keynr; + KEY_PART_INFO* key_part = key_info->key_part; + KEY_PART_INFO* end = key_part + key_info->key_parts; + char* buff_start = buff; + enum_field_types mysql_type; + Field* field; + + DBUG_ENTER("store_key_val_for_row"); + + bzero(buff, buff_len); + *key_is_null = TRUE; + + for (; key_part != end; key_part++) { + uchar sorted[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'}; + ibool part_is_null = FALSE; + + if (key_part->null_bit) { + if (record[key_part->null_offset] & + key_part->null_bit) { + *buff = 1; + part_is_null = TRUE; + } else { + *buff = 0; + } + buff++; + } + if (!part_is_null) *key_is_null = FALSE; + + field = key_part->field; + mysql_type = field->type(); + + if (mysql_type == MYSQL_TYPE_VARCHAR) { + /* >= 5.0.3 true VARCHAR */ + ulint lenlen; + ulint len; + const byte* data; + ulint key_len; + ulint true_len; + CHARSET_INFO* cs; + int error=0; + + key_len = key_part->length; + + if (part_is_null) { + buff += key_len + 2; + + continue; + } + cs = field->charset(); + + lenlen = (ulint) + (((Field_varstring*)field)->length_bytes); + + data = row_mysql_read_true_varchar(&len, + (byte*) (record + + (ulint)get_field_offset(table, field)), + lenlen); + + true_len = len; + + /* For multi byte character sets we need to calculate + the true length of the key */ + + if (len > 0 && cs->mbmaxlen > 1) { + true_len = (ulint) cs->cset->well_formed_len(cs, + (const char *) data, + (const char *) data + len, + (uint) (key_len / + cs->mbmaxlen), + &error); + } + + /* In a column prefix index, we may need to truncate + the stored value: */ + + if (true_len > key_len) { + true_len = key_len; + } + + memcpy(sorted, data, true_len); + wsrep_innobase_mysql_sort( + mysql_type, cs->number, sorted, true_len); + + if (wsrep_protocol_version > 1) { + memcpy(buff, sorted, true_len); + /* Note that we always reserve the maximum possible + length of the true VARCHAR in the key value, though + only len first bytes after the 2 length bytes contain + actual data. The rest of the space was reset to zero + in the bzero() call above. */ + buff += true_len; + } else { + buff += key_len; + } + } else if (mysql_type == MYSQL_TYPE_TINY_BLOB + || mysql_type == MYSQL_TYPE_MEDIUM_BLOB + || mysql_type == MYSQL_TYPE_BLOB + || mysql_type == MYSQL_TYPE_LONG_BLOB + /* MYSQL_TYPE_GEOMETRY data is treated + as BLOB data in innodb. */ + || mysql_type == MYSQL_TYPE_GEOMETRY) { + + CHARSET_INFO* cs; + ulint key_len; + ulint true_len; + int error=0; + ulint blob_len; + const byte* blob_data; + + ut_a(key_part->key_part_flag & HA_PART_KEY_SEG); + + key_len = key_part->length; + + if (part_is_null) { + buff += key_len + 2; + + continue; + } + + cs = field->charset(); + + blob_data = row_mysql_read_blob_ref(&blob_len, + (byte*) (record + + (ulint)get_field_offset(table, field)), + (ulint) field->pack_length()); + + true_len = blob_len; + + ut_a(get_field_offset(table, field) + == key_part->offset); + + /* For multi byte character sets we need to calculate + the true length of the key */ + + if (blob_len > 0 && cs->mbmaxlen > 1) { + true_len = (ulint) cs->cset->well_formed_len(cs, + (const char *) blob_data, + (const char *) blob_data + + blob_len, + (uint) (key_len / + cs->mbmaxlen), + &error); + } + + /* All indexes on BLOB and TEXT are column prefix + indexes, and we may need to truncate the data to be + stored in the key value: */ + + if (true_len > key_len) { + true_len = key_len; + } + + memcpy(sorted, blob_data, true_len); + wsrep_innobase_mysql_sort( + mysql_type, cs->number, sorted, true_len); + + memcpy(buff, sorted, true_len); + + /* Note that we always reserve the maximum possible + length of the BLOB prefix in the key value. */ + if (wsrep_protocol_version > 1) { + buff += true_len; + } else { + buff += key_len; + } + } else { + /* Here we handle all other data types except the + true VARCHAR, BLOB and TEXT. Note that the column + value we store may be also in a column prefix + index. */ + + CHARSET_INFO* cs; + ulint true_len; + ulint key_len; + const uchar* src_start; + int error=0; + enum_field_types real_type; + + key_len = key_part->length; + + if (part_is_null) { + buff += key_len; + + continue; + } + + src_start = record + key_part->offset; + real_type = field->real_type(); + true_len = key_len; + + /* Character set for the field is defined only + to fields whose type is string and real field + type is not enum or set. For these fields check + if character set is multi byte. */ + + if (real_type != MYSQL_TYPE_ENUM + && real_type != MYSQL_TYPE_SET + && ( mysql_type == MYSQL_TYPE_VAR_STRING + || mysql_type == MYSQL_TYPE_STRING)) { + + cs = field->charset(); + + /* For multi byte character sets we need to + calculate the true length of the key */ + + if (key_len > 0 && cs->mbmaxlen > 1) { + + true_len = (ulint) + cs->cset->well_formed_len(cs, + (const char *)src_start, + (const char *)src_start + + key_len, + (uint) (key_len / + cs->mbmaxlen), + &error); + } + memcpy(sorted, src_start, true_len); + wsrep_innobase_mysql_sort( + mysql_type, cs->number, sorted, true_len); + memcpy(buff, sorted, true_len); + } else { + memcpy(buff, src_start, true_len); + } + buff += true_len; + + /* Pad the unused space with spaces. */ + +#ifdef REMOVED + if (true_len < key_len) { + ulint pad_len = key_len - true_len; + ut_a(!(pad_len % cs->mbminlen)); + + cs->cset->fill(cs, buff, pad_len, + 0x20 /* space */); + buff += pad_len; + } +#endif /* REMOVED */ + } + } + + ut_a(buff <= buff_start + buff_len); + + DBUG_RETURN((uint)(buff - buff_start)); +} +#endif /* WITH_WSREP */ UNIV_INTERN uint ha_innobase::store_key_val_for_row( @@ -6302,6 +6733,9 @@ ha_innobase::write_row( ulint error = 0; int error_result= 0; ibool auto_inc_used= FALSE; +#ifdef WITH_WSREP + ibool auto_inc_inserted= FALSE; /* if NULL was inserted */ +#endif ulint sql_command; trx_t* trx = thd_to_trx(user_thd); @@ -6330,8 +6764,17 @@ ha_innobase::write_row( if ((sql_command == SQLCOM_ALTER_TABLE || sql_command == SQLCOM_OPTIMIZE || sql_command == SQLCOM_CREATE_INDEX +#ifdef WITH_WSREP + || (wsrep_on(user_thd) && sql_command == SQLCOM_LOAD) +#endif /* WITH_WSREP */ || sql_command == SQLCOM_DROP_INDEX) && num_write_row >= 10000) { +#ifdef WITH_WSREP + if (wsrep_on(user_thd) && sql_command == SQLCOM_LOAD) { + WSREP_DEBUG("forced trx split for LOAD: %s", + wsrep_thd_query(user_thd)); + } +#endif /* WITH_WSREP */ /* ALTER TABLE is COMMITted at every 10000 copied rows. The IX table lock for the original table has to be re-issued. As this method will be called on a temporary table where the @@ -6403,7 +6846,9 @@ no_commit: /* Reset the error code before calling innobase_get_auto_increment(). */ prebuilt->autoinc_error = DB_SUCCESS; - +#ifdef WITH_WSREP + auto_inc_inserted= (table->next_number_field->val_int() == 0); +#endif if ((error = update_auto_increment())) { /* We don't want to mask autoinc overflow errors. */ @@ -6486,6 +6931,30 @@ no_commit: case SQLCOM_REPLACE_SELECT: goto set_max_autoinc; +#ifdef WITH_WSREP + /* workaround for LP bug #355000, retrying the insert */ + case SQLCOM_INSERT: + if (wsrep_on(current_thd) && + auto_inc_inserted && + wsrep_drupal_282555_workaround && + !thd_test_options(current_thd, + OPTION_NOT_AUTOCOMMIT | + OPTION_BEGIN)) { + WSREP_DEBUG( + "retrying insert: %s", + (*wsrep_thd_query(current_thd)) ? + wsrep_thd_query(current_thd) : + (char *)"void"); + error= DB_SUCCESS; + wsrep_thd_set_conflict_state( + current_thd, MUST_ABORT); + innobase_srv_conc_exit_innodb(prebuilt->trx); + /* jump straight to func exit over + * later wsrep hooks */ + goto func_exit; + } + break; +#endif default: break; } @@ -6534,6 +7003,20 @@ report_error: error_result = convert_error_code_to_mysql((int) error, prebuilt->table->flags, user_thd); +#ifdef WITH_WSREP + if (!error_result && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && + wsrep_on(user_thd) && !wsrep_consistency_check(user_thd) && + (sql_command != SQLCOM_LOAD || + thd_binlog_format(user_thd) == BINLOG_FORMAT_ROW)) { + + if (wsrep_append_keys(user_thd, false, record, NULL)) { + DBUG_PRINT("wsrep", ("row key failed")); + error_result = HA_ERR_INTERNAL_ERROR; + goto wsrep_error; + } + } +wsrep_error: +#endif if (error_result == HA_FTS_INVALID_DOCID) { my_error(HA_FTS_INVALID_DOCID, MYF(0)); @@ -6823,7 +7306,84 @@ calc_row_difference( return(error); } +#ifdef WITH_WSREP +static +int +wsrep_calc_row_hash( +/*================*/ + byte* digest, /*!< in/out: md5 sum */ + const uchar* row, /*!< in: row in MySQL format */ + TABLE* table, /*!< in: table in MySQL data + dictionary */ + row_prebuilt_t* prebuilt, /*!< in: InnoDB prebuilt struct */ + THD* thd) /*!< in: user thread */ +{ + Field* field; + enum_field_types field_mysql_type; + uint n_fields; + ulint len; + const byte* ptr; + ulint col_type; + uint i; + + my_MD5Context ctx; + my_MD5Init (&ctx); + + n_fields = table->s->fields; + + for (i = 0; i < n_fields; i++) { + byte null_byte=0; + byte true_byte=1; + + field = table->field[i]; + + ptr = (const byte*) row + get_field_offset(table, field); + len = field->pack_length(); + + field_mysql_type = field->type(); + + col_type = prebuilt->table->cols[i].mtype; + + switch (col_type) { + + case DATA_BLOB: + ptr = row_mysql_read_blob_ref(&len, ptr, len); + + break; + + case DATA_VARCHAR: + case DATA_BINARY: + case DATA_VARMYSQL: + if (field_mysql_type == MYSQL_TYPE_VARCHAR) { + /* This is a >= 5.0.3 type true VARCHAR where + the real payload data length is stored in + 1 or 2 bytes */ + + ptr = row_mysql_read_true_varchar( + &len, ptr, + (ulint) + (((Field_varstring*)field)->length_bytes)); + + } + break; + default: + ; + } + + if (field->null_ptr && + field_in_record_is_null(table, field, (char*) row)) { + my_MD5Update (&ctx, &null_byte, 1); + } else { + my_MD5Update (&ctx, &true_byte, 1); + my_MD5Update (&ctx, ptr, len); + } + } + my_MD5Final (digest, &ctx); + + return(0); +} +#endif /* WITH_WSREP */ /**********************************************************************//** Updates a row given as a parameter to a new value. Note that we are given whole rows, not just the fields which are updated: this incurs some @@ -6955,6 +7515,20 @@ func_exit: innobase_active_small(); +#ifdef WITH_WSREP + if (!error && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && + wsrep_on(user_thd)) { + + DBUG_PRINT("wsrep", ("update row key")); + + if (wsrep_append_keys(user_thd, false, old_row, new_row)) { + DBUG_PRINT("wsrep", ("row key failed")); + error = HA_ERR_INTERNAL_ERROR; + goto wsrep_error; + } + } +wsrep_error: +#endif DBUG_RETURN(error); } @@ -7000,6 +7574,18 @@ ha_innobase::delete_row( innobase_active_small(); +#ifdef WITH_WSREP + if (!error && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && + wsrep_on(user_thd)) { + + if (wsrep_append_keys(user_thd, false, record, NULL)) { + DBUG_PRINT("wsrep", ("delete fail")); + error = HA_ERR_INTERNAL_ERROR; + goto wsrep_error; + } + } +wsrep_error: +#endif DBUG_RETURN(error); } @@ -8022,7 +8608,376 @@ ha_innobase::ft_end() rnd_end(); } +#ifdef WITH_WSREP +extern dict_index_t* +wsrep_dict_foreign_find_index( + dict_table_t* table, + const char** columns, + ulint n_cols, + dict_index_t* types_idx, + ibool check_charsets, + ulint check_null); + + +extern ulint +wsrep_append_foreign_key( +/*===========================*/ + trx_t* trx, /*!< in: trx */ + dict_foreign_t* foreign, /*!< in: foreign key constraint */ + const rec_t* rec, /*!<in: clustered index record */ + dict_index_t* index, /*!<in: clustered index */ + ibool referenced, /*!<in: is check for referenced table */ + ibool shared) /*!<in: is shared access */ +{ + ut_a(trx); + THD* thd = (THD*)trx->mysql_thd; + ulint rcode = DB_SUCCESS; + char cache_key[513] = {'\0'}; + int cache_key_len; + + if (!wsrep_on(trx->mysql_thd) || + wsrep_thd_exec_mode(thd) != LOCAL_STATE) + return DB_SUCCESS; + + if (!thd || !foreign || + (!foreign->referenced_table && !foreign->foreign_table)) + { + WSREP_INFO("FK: %s missing in: %s", + (!thd) ? "thread" : + ((!foreign) ? "constraint" : + ((!foreign->referenced_table) ? + "referenced table" : "foreign table")), + (thd && wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + return DB_ERROR; + } + + if ( !((referenced) ? + foreign->referenced_table : foreign->foreign_table)) + { + WSREP_DEBUG("pulling %s table into cache", + (referenced) ? "referenced" : "foreign"); + mutex_enter(&(dict_sys->mutex)); + if (referenced) + { + foreign->referenced_table = + dict_table_get_low( + foreign->referenced_table_name_lookup); + if (foreign->referenced_table) + { + foreign->referenced_index = + wsrep_dict_foreign_find_index( + foreign->referenced_table, + foreign->referenced_col_names, + foreign->n_fields, + foreign->foreign_index, + TRUE, FALSE); + } + } + else + { + foreign->foreign_table = + dict_table_get_low( + foreign->foreign_table_name_lookup); + if (foreign->foreign_table) + { + foreign->foreign_index = + wsrep_dict_foreign_find_index( + foreign->foreign_table, + foreign->foreign_col_names, + foreign->n_fields, + foreign->referenced_index, + TRUE, FALSE); + } + } + mutex_exit(&(dict_sys->mutex)); + } + + if ( !((referenced) ? + foreign->referenced_table : foreign->foreign_table)) + { + WSREP_WARN("FK: %s missing in query: %s", + (!foreign->referenced_table) ? + "referenced table" : "foreign table", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + return DB_ERROR; + } + byte key[WSREP_MAX_SUPPORTED_KEY_LENGTH+1]; + ulint len = WSREP_MAX_SUPPORTED_KEY_LENGTH; + + dict_index_t *idx_target = (referenced) ? + foreign->referenced_index : index; + dict_index_t *idx = (referenced) ? + UT_LIST_GET_FIRST(foreign->referenced_table->indexes) : + UT_LIST_GET_FIRST(foreign->foreign_table->indexes); + int i = 0; + while (idx != NULL && idx != idx_target) { + idx = UT_LIST_GET_NEXT(indexes, idx); + i++; + } + ut_a(idx); + key[0] = (char)i; + + rcode = wsrep_rec_get_foreign_key( + &key[1], &len, rec, index, idx, + wsrep_protocol_version > 1); + if (rcode != DB_SUCCESS) { + WSREP_ERROR( + "FK key set failed: %lu (%lu %lu), index: %s %s, %s", + rcode, referenced, shared, + (index && index->name) ? index->name : + "void index", + (index && index->table_name) ? index->table_name : + "void table", + wsrep_thd_query(thd)); + return rcode; + } + strncpy(cache_key, + (wsrep_protocol_version > 1) ? + ((referenced) ? + foreign->referenced_table->name : + foreign->foreign_table->name) : + foreign->foreign_table->name, sizeof(cache_key) - 1); + cache_key_len = strlen(cache_key); +#ifdef WSREP_DEBUG_PRINT + ulint j; + fprintf(stderr, "FK parent key, table: %s %s len: %lu ", + cache_key, (shared) ? "shared" : "exclusive", len+1); + for (j=0; j<len+1; j++) { + fprintf(stderr, " %hhX, ", key[j]); + } + fprintf(stderr, "\n"); +#endif + char *p = strchr(cache_key, '/'); + if (p) { + *p = '\0'; + } else { + WSREP_WARN("unexpected foreign key table %s %s", + foreign->referenced_table->name, + foreign->foreign_table->name); + } + + wsrep_key_part_t wkey_part[3]; + wsrep_key_t wkey = {wkey_part, 3}; + if (!wsrep_prepare_key_for_innodb( + (const uchar*)cache_key, + cache_key_len + 1, + (const uchar*)key, len+1, + wkey_part, + &wkey.key_parts_len)) { + WSREP_WARN("key prepare failed for cascaded FK: %s", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + return DB_ERROR; + } + rcode = (int)wsrep->append_key( + wsrep, + wsrep_trx_handle(thd, trx), + &wkey, + 1, + shared); + if (rcode) { + DBUG_PRINT("wsrep", ("row key failed: %lu", rcode)); + WSREP_ERROR("Appending cascaded fk row key failed: %s, %lu", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void", rcode); + return DB_ERROR; + } + + return DB_SUCCESS; +} + +static int +wsrep_append_key( +/*==================*/ + THD *thd, + trx_t *trx, + TABLE_SHARE *table_share, + TABLE *table, + const char* key, + uint16_t key_len, + bool shared +) +{ + DBUG_ENTER("wsrep_append_key"); +#ifdef WSREP_DEBUG_PRINT + fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s ", + (shared) ? "Shared" : "Exclusive", + wsrep_thd_thread_id(thd), trx->id, key_len, + table_share->table_name.str); + for (int i=0; i<key_len; i++) { + fprintf(stderr, "%hhX, ", key[i]); + } + fprintf(stderr, "\n"); +#endif + wsrep_key_part_t wkey_part[3]; + wsrep_key_t wkey = {wkey_part, 3}; + if (!wsrep_prepare_key_for_innodb( + (const uchar*)table_share->table_cache_key.str, + table_share->table_cache_key.length, + (const uchar*)key, key_len, + wkey_part, + &wkey.key_parts_len)) { + WSREP_WARN("key prepare failed for: %s", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); + } + + int rcode = (int)wsrep->append_key( + wsrep, + wsrep_trx_handle(thd, trx), + &wkey, + 1, + shared); + if (rcode) { + DBUG_PRINT("wsrep", ("row key failed: %d", rcode)); + WSREP_WARN("Appending row key failed: %s, %d", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void", rcode); + DBUG_RETURN(rcode); + } + DBUG_RETURN(0); +} + +ibool +wsrep_is_cascding_foreign_key_parent( + dict_table_t* table, /*!< in: InnoDB table */ + dict_index_t* index /*!< in: InnoDB index */ +) { + // return referenced_by_foreign_key(); + dict_foreign_t* fk = dict_table_get_referenced_constraint(table, index); + if (fk && + (fk->type & DICT_FOREIGN_ON_UPDATE_CASCADE || + fk->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) + ) { + return TRUE; + } + return FALSE; +} + +int +ha_innobase::wsrep_append_keys( +/*==================*/ + THD *thd, + bool shared, + const uchar* record0, /* in: row in MySQL format */ + const uchar* record1) /* in: row in MySQL format */ +{ + DBUG_ENTER("wsrep_append_keys"); + + bool key_appended = false; + trx_t *trx = thd_to_trx(thd); + + if (table_share && table_share->tmp_table != NO_TMP_TABLE) { + WSREP_DEBUG("skipping tmp table DML: THD: %lu tmp: %d SQL: %s", + wsrep_thd_thread_id(thd), + table_share->tmp_table, + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + DBUG_RETURN(0); + } + + if (wsrep_protocol_version == 0) { + uint len; + char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; + char *key = &keyval[0]; + KEY *key_info = table->key_info; + ibool is_null; + + len = wsrep_store_key_val_for_row( + table, 0, key, key_info->key_length, record0, &is_null); + if (!is_null) { + int rcode = wsrep_append_key( + thd, trx, table_share, table, keyval, + len, shared); + if (rcode) DBUG_RETURN(rcode); + } + else + { + WSREP_DEBUG("NULL key skipped (proto 0): %s", + wsrep_thd_query(thd)); + } + } else { + ut_a(table->s->keys <= 256); + uint i; + for (i=0; i<table->s->keys; ++i) { + uint len; + char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; + char keyval1[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; + char *key0 = &keyval0[1]; + char *key1 = &keyval1[1]; + KEY *key_info = table->key_info + i; + ibool is_null; + + keyval0[0] = (char)i; + keyval1[0] = (char)i; + + if (key_info->flags & HA_NOSAME || + referenced_by_foreign_key()) { + if (key_info->flags & HA_NOSAME || shared) + key_appended = true; + + len = wsrep_store_key_val_for_row( + table, i, key0, key_info->key_length, + record0, &is_null); + if (!is_null) { + int rcode = wsrep_append_key( + thd, trx, table_share, table, + keyval0, len+1, shared); + if (rcode) DBUG_RETURN(rcode); + } + else + { + WSREP_DEBUG("NULL key skipped: %s", + wsrep_thd_query(thd)); + } + if (record1) { + len = wsrep_store_key_val_for_row( + table, i, key1, key_info->key_length, + record1, &is_null); + if (!is_null && memcmp(key0, key1, len)) { + int rcode = wsrep_append_key( + thd, trx, table_share, + table, + keyval1, len+1, shared); + if (rcode) DBUG_RETURN(rcode); + } + } + } + } + } + + /* if no PK, calculate hash of full row, to be the key value */ + if (!key_appended && wsrep_certify_nonPK) { + uchar digest[16]; + int rcode; + + wsrep_calc_row_hash(digest, record0, table, prebuilt, thd); + if ((rcode = wsrep_append_key(thd, trx, table_share, table, + (const char*) digest, 16, + shared))) { + DBUG_RETURN(rcode); + } + + if (record1) { + wsrep_calc_row_hash( + digest, record1, table, prebuilt, thd); + if ((rcode = wsrep_append_key(thd, trx, table_share, + table, + (const char*) digest, + 16, shared))) { + DBUG_RETURN(rcode); + } + } + DBUG_RETURN(0); + } + + DBUG_RETURN(0); +} +#endif /*********************************************************************//** Stores a reference to the current row to 'ref' field of the handle. Note that in the case where we have generated the clustered index for the @@ -11426,11 +12381,18 @@ ha_innobase::external_lock( /* used by test case */ DBUG_EXECUTE_IF("no_innodb_binlog_errors", skip = 1;); if (!skip) { +#ifdef WITH_WSREP + if (!wsrep_on(thd) || wsrep_thd_exec_mode(thd) == LOCAL_STATE) + { +#endif /* WITH_WSREP */ my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0), " InnoDB is limited to row-logging when " "transaction isolation level is " "READ COMMITTED or READ UNCOMMITTED."); DBUG_RETURN(HA_ERR_LOGGING_IMPOSSIBLE); +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ } } @@ -12798,6 +13760,9 @@ innobase_xa_prepare( to the session variable take effect only in the next transaction */ if (!trx->support_xa) { +#ifdef WITH_WSREP + thd_get_xid(thd, (MYSQL_XID*) &trx->xid); +#endif // WITH_WSREP return(0); } @@ -14537,6 +15502,278 @@ static SHOW_VAR innodb_status_variables_export[]= { static struct st_mysql_storage_engine innobase_storage_engine= { MYSQL_HANDLERTON_INTERFACE_VERSION }; +#ifdef WITH_WSREP +void +wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno) +{ + WSREP_ERROR("Trx %lld tries to abort slave trx %lld. This could be " + "caused by:\n\t" + "1) unsupported configuration options combination, please check documentation.\n\t" + "2) a bug in the code.\n\t" + "3) a database corruption.\n Node consistency compromized, " + "need to abort. Restart the node to resync with cluster.", + (long long)bf_seqno, (long long)victim_seqno); + abort(); +} +int +wsrep_innobase_kill_one_trx(const trx_t *bf_trx, trx_t *victim_trx, ibool signal) +{ + DBUG_ENTER("wsrep_innobase_kill_one_trx"); + THD *bf_thd = (THD *)((bf_trx) ? bf_trx->mysql_thd : NULL); + THD *thd = (THD *) victim_trx->mysql_thd; + int64_t bf_seqno = (bf_thd) ? wsrep_thd_trx_seqno(bf_thd) : 0; + + if (!bf_thd) bf_thd = (bf_trx) ? (THD *)bf_trx->mysql_thd : NULL; + + if (!thd) { + DBUG_PRINT("wsrep", ("no thd for conflicting lock")); + WSREP_WARN("no THD for trx: %lu", victim_trx->id); + DBUG_RETURN(1); + } + if (!bf_thd) { + DBUG_PRINT("wsrep", ("no BF thd for conflicting lock")); + WSREP_WARN("no BF THD for trx: %lu", (bf_trx) ? bf_trx->id : 0); + DBUG_RETURN(1); + } + + WSREP_LOG_CONFLICT(bf_thd, thd, TRUE); + + WSREP_DEBUG("BF kill (%lu, seqno: %lld), victim: (%lu) trx: %lu", + signal, (long long)bf_seqno, + wsrep_thd_thread_id(thd), + victim_trx->id); + + WSREP_DEBUG("Aborting query: %s", + (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void"); + + wsrep_thd_LOCK(thd); + + if (wsrep_thd_query_state(thd) == QUERY_EXITING) { + WSREP_DEBUG("kill trx EXITING for %lu", victim_trx->id); + wsrep_thd_UNLOCK(thd); + DBUG_RETURN(0); + } + if(wsrep_thd_exec_mode(thd) != LOCAL_STATE) { + WSREP_DEBUG("withdraw for BF trx: %lu, state: %d", + victim_trx->id, + wsrep_thd_conflict_state(thd)); + } + + switch (wsrep_thd_conflict_state(thd)) { + case NO_CONFLICT: + wsrep_thd_set_conflict_state(thd, MUST_ABORT); + break; + case MUST_ABORT: + WSREP_DEBUG("victim %lu in MUST ABORT state", + victim_trx->id); + wsrep_thd_UNLOCK(thd); + wsrep_thd_awake(bf_thd, thd, signal); + DBUG_RETURN(0); + break; + case ABORTED: + case ABORTING: // fall through + default: + WSREP_DEBUG("victim %lu in state %d", + victim_trx->id, wsrep_thd_conflict_state(thd)); + wsrep_thd_UNLOCK(thd); + DBUG_RETURN(0); + break; + } + + switch (wsrep_thd_query_state(thd)) { + case QUERY_COMMITTING: + enum wsrep_status rcode; + + WSREP_DEBUG("kill query for: %ld", + wsrep_thd_thread_id(thd)); + wsrep_thd_awake(bf_thd, thd, signal); + WSREP_DEBUG("kill trx QUERY_COMMITTING for %lu", + victim_trx->id); + + if (wsrep_thd_exec_mode(thd) == REPL_RECV) { + wsrep_abort_slave_trx(bf_seqno, + wsrep_thd_trx_seqno(thd)); + } else { + rcode = wsrep->abort_pre_commit( + wsrep, bf_seqno, + (wsrep_trx_id_t)victim_trx->id + ); + + switch (rcode) { + case WSREP_WARNING: + WSREP_DEBUG("cancel commit warning: %lu", + victim_trx->id); + wsrep_thd_UNLOCK(thd); + DBUG_RETURN(1); + break; + case WSREP_OK: + break; + default: + WSREP_ERROR( + "cancel commit bad exit: %d %lu", + rcode, + victim_trx->id); + /* unable to interrupt, must abort */ + /* note: kill_mysql() will block, if we cannot. + * kill the lock holder first. + */ + abort(); + break; + } + } + break; + case QUERY_EXEC: + /* it is possible that victim trx is itself waiting for some + * other lock. We need to cancel this waiting + */ + WSREP_DEBUG("kill trx QUERY_EXEC for %lu", victim_trx->id); + + victim_trx->lock.was_chosen_as_deadlock_victim= TRUE; + if (victim_trx->lock.wait_lock) { + WSREP_DEBUG("victim has wait flag: %ld", + wsrep_thd_thread_id(thd)); + lock_t* wait_lock = victim_trx->lock.wait_lock; + if (wait_lock) { + WSREP_DEBUG("canceling wait lock"); + victim_trx->lock.was_chosen_as_deadlock_victim= TRUE; + lock_cancel_waiting_and_release(wait_lock); + } + + wsrep_thd_awake(bf_thd, thd, signal); + } else { + /* abort currently executing query */ + DBUG_PRINT("wsrep",("sending KILL_QUERY to: %ld", + wsrep_thd_thread_id(thd))); + WSREP_DEBUG("kill query for: %ld", + wsrep_thd_thread_id(thd)); + wsrep_thd_awake(bf_thd, thd, signal); + + /* for BF thd, we need to prevent him from committing */ + if (wsrep_thd_exec_mode(thd) == REPL_RECV) { + wsrep_abort_slave_trx(bf_seqno, + wsrep_thd_trx_seqno(thd)); + } + } + break; + case QUERY_IDLE: + { + bool skip_abort= false; + wsrep_aborting_thd_t abortees; + + WSREP_DEBUG("kill IDLE for %lu", victim_trx->id); + + if (wsrep_thd_exec_mode(thd) == REPL_RECV) { + WSREP_DEBUG("kill BF IDLE, seqno: %lld", + (long long)wsrep_thd_trx_seqno(thd)); + wsrep_thd_UNLOCK(thd); + wsrep_abort_slave_trx(bf_seqno, + wsrep_thd_trx_seqno(thd)); + DBUG_RETURN(0); + } + /* This will lock thd from proceeding after net_read() */ + wsrep_thd_set_conflict_state(thd, ABORTING); + + mysql_mutex_lock(&LOCK_wsrep_rollback); + + abortees = wsrep_aborting_thd; + while (abortees && !skip_abort) { + /* check if we have a kill message for this already */ + if (abortees->aborting_thd == thd) { + skip_abort = true; + WSREP_WARN("duplicate thd aborter %lu", + wsrep_thd_thread_id(thd)); + } + abortees = abortees->next; + } + if (!skip_abort) { + wsrep_aborting_thd_t aborting = (wsrep_aborting_thd_t) + my_malloc(sizeof(struct wsrep_aborting_thd), + MYF(0)); + aborting->aborting_thd = thd; + aborting->next = wsrep_aborting_thd; + wsrep_aborting_thd = aborting; + DBUG_PRINT("wsrep",("enqueuing trx abort for %lu", + wsrep_thd_thread_id(thd))); + WSREP_DEBUG("enqueuing trx abort for (%lu)", + wsrep_thd_thread_id(thd)); + } + + DBUG_PRINT("wsrep",("signalling wsrep rollbacker")); + WSREP_DEBUG("signaling aborter"); + mysql_cond_signal(&COND_wsrep_rollback); + mysql_mutex_unlock(&LOCK_wsrep_rollback); + + break; + } + default: + WSREP_WARN("bad wsrep query state: %d", + wsrep_thd_query_state(thd)); + break; + } + wsrep_thd_UNLOCK(thd); + + DBUG_RETURN(0); +} +static int +wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, + my_bool signal) +{ + DBUG_ENTER("wsrep_innobase_abort_thd"); + trx_t* victim_trx = thd_to_trx(victim_thd); + trx_t* bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL; + WSREP_DEBUG("abort transaction: BF: %s victim: %s", + wsrep_thd_query(bf_thd), + wsrep_thd_query(victim_thd)); + + if (victim_trx) + { + int rcode = wsrep_innobase_kill_one_trx(bf_trx, victim_trx, + signal); + wsrep_srv_conc_cancel_wait(victim_trx); + DBUG_RETURN(rcode); + } else { + WSREP_DEBUG("victim does not have transaction"); + wsrep_thd_LOCK(victim_thd); + wsrep_thd_set_conflict_state(victim_thd, MUST_ABORT); + wsrep_thd_UNLOCK(victim_thd); + wsrep_thd_awake(bf_thd, victim_thd, signal); + } + DBUG_RETURN(-1); +} + +static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid) +{ + DBUG_ASSERT(hton == innodb_hton_ptr); + if (wsrep_is_wsrep_xid(xid)) { + mtr_t mtr; + mtr_start(&mtr); + trx_sys_update_wsrep_checkpoint(xid, &mtr); + mtr_commit(&mtr); + return 0; + } else { + return 1; + } +} + +static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid) +{ + DBUG_ASSERT(hton == innodb_hton_ptr); + trx_sys_read_wsrep_checkpoint(xid); + return 0; +} + +static void +wsrep_fake_trx_id( +/*==================*/ + handlerton *hton, + THD *thd) /*!< in: user thread handle */ +{ + trx_id_t trx_id = trx_sys_get_new_trx_id(); + + (void *)wsrep_trx_handle_for_id(wsrep_thd_trx_handle(thd), trx_id); +} + +#endif /* WITH_WSREP */ /* plugin options */ static MYSQL_SYSVAR_ENUM(checksum_algorithm, srv_checksum_algorithm, @@ -15116,6 +16353,40 @@ static MYSQL_SYSVAR_UINT(change_buffering_debug, ibuf_debug, NULL, NULL, 0, 0, 2, 0); #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ +#ifdef WITH_INNODB_DISALLOW_WRITES +/******************************************************* + * innobase_disallow_writes variable definition * + *******************************************************/ + +/* Must always init to FALSE. */ +static my_bool innobase_disallow_writes = FALSE; + +/************************************************************************** +An "update" method for innobase_disallow_writes variable. */ +static +void +innobase_disallow_writes_update( +/*============================*/ + THD* thd, /* in: thread handle */ + st_mysql_sys_var* var, /* in: pointer to system + variable */ + void* var_ptr, /* out: pointer to dynamic + variable */ + const void* save) /* in: temporary storage */ +{ + *(my_bool*)var_ptr = *(my_bool*)save; + ut_a(srv_allow_writes_event); + if (*(my_bool*)var_ptr) + os_event_reset(srv_allow_writes_event); + else + os_event_set(srv_allow_writes_event); +} + +static MYSQL_SYSVAR_BOOL(disallow_writes, innobase_disallow_writes, + PLUGIN_VAR_NOCMDOPT, + "Tell InnoDB to stop any writes to disk", + NULL, innobase_disallow_writes_update, FALSE); +#endif /* WITH_INNODB_DISALLOW_WRITES */ static MYSQL_SYSVAR_BOOL(random_read_ahead, srv_random_read_ahead, PLUGIN_VAR_NOCMDARG, "Whether to use read ahead for random access within an extent.", @@ -15271,6 +16542,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG MYSQL_SYSVAR(change_buffering_debug), #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ +#ifdef WITH_INNODB_DISALLOW_WRITES + MYSQL_SYSVAR(disallow_writes), +#endif /* WITH_INNODB_DISALLOW_WRITES */ MYSQL_SYSVAR(random_read_ahead), MYSQL_SYSVAR(read_ahead_threshold), MYSQL_SYSVAR(io_capacity), diff --git a/storage/innobase/handler/ha_innodb.h b/storage/innobase/handler/ha_innodb.h index e56a1ec52e3..889fc188999 100644 --- a/storage/innobase/handler/ha_innodb.h +++ b/storage/innobase/handler/ha_innodb.h @@ -111,6 +111,10 @@ class ha_innobase: public handler dict_index_t* innobase_get_index(uint keynr); int info_low(uint flag, dict_stats_upd_option_t stats_upd_option); +#ifdef WITH_WSREP + int wsrep_append_keys(THD *thd, bool shared, + const uchar* record0, const uchar* record1); +#endif /* Init values for the class: */ public: ha_innobase(handlerton *hton, TABLE_SHARE *table_arg); @@ -371,6 +375,40 @@ bool thd_sqlcom_can_generate_row_events(const MYSQL_THD thd); */ extern void mysql_bin_log_commit_pos(THD *thd, ulonglong *out_pos, const char **out_file); +#ifdef WITH_WSREP +#include <wsrep_mysqld.h> +//extern "C" int wsrep_trx_order_before(void *thd1, void *thd2); + +extern "C" bool wsrep_thd_is_wsrep_on(THD *thd); + +extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd); +extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd); +extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd); +extern "C" const char * wsrep_thd_exec_mode_str(THD *thd); +extern "C" const char * wsrep_thd_conflict_state_str(THD *thd); +extern "C" const char * wsrep_thd_query_state_str(THD *thd); +extern "C" wsrep_trx_handle_t* wsrep_thd_trx_handle(THD *thd); + +extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode); +extern "C" void wsrep_thd_set_query_state( + THD *thd, enum wsrep_query_state state); +extern "C" void wsrep_thd_set_conflict_state( + THD *thd, enum wsrep_conflict_state state); + +extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id); + +extern "C"void wsrep_thd_LOCK(THD *thd); +extern "C"void wsrep_thd_UNLOCK(THD *thd); +extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd); +extern "C" time_t wsrep_thd_query_start(THD *thd); +extern "C" my_thread_id wsrep_thd_thread_id(THD *thd); +extern "C" int64_t wsrep_thd_trx_seqno(THD *thd); +extern "C" query_id_t wsrep_thd_query_id(THD *thd); +extern "C" char * wsrep_thd_query(THD *thd); +extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd); +extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); +extern "C" void wsrep_thd_awake(THD* bf_thd, THD *thd, my_bool signal); +#endif typedef struct trx_struct trx_t; extern const struct _ft_vft ft_vft_result; @@ -417,6 +455,9 @@ innobase_index_name_is_reserved( const KEY* key_info, /*!< in: Indexes to be created */ ulint num_of_keys); /*!< in: Number of indexes to be created. */ +#ifdef WITH_WSREP +extern "C" int wsrep_trx_is_aborting(void *thd_ptr); +#endif /*********************************************************************//** Retrieve the FTS Relevance Ranking result for doc with doc_id of prebuilt->fts_doc_id diff --git a/storage/innobase/handler/handler0alter.cc b/storage/innobase/handler/handler0alter.cc index e1a10ade9ad..fc29d767255 100644 --- a/storage/innobase/handler/handler0alter.cc +++ b/storage/innobase/handler/handler0alter.cc @@ -37,6 +37,10 @@ Smart ALTER TABLE #include "srv0mon.h" #include "fts0priv.h" +#ifdef WITH_WSREP +//#include "wsrep_api.h" +#include <sql_acl.h> // PROCESS_ACL +#endif #include "ha_innodb.h" /*************************************************************//** diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index ea7e996dfa8..c3f3807bb60 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -422,6 +422,9 @@ be REC_VERSION_56_MAX_INDEX_COL_LEN (3072) bytes */ /** Defines the maximum fixed length column size */ #define DICT_MAX_FIXED_COL_LEN DICT_ANTELOPE_MAX_INDEX_COL_LEN +#ifdef WITH_WSREP +#define WSREP_MAX_SUPPORTED_KEY_LENGTH 3500 +#endif /* WITH_WSREP */ /** Data structure for a field in an index */ struct dict_field_struct{ diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h index 5512bf7c62f..a2e1fca73cf 100644 --- a/storage/innobase/include/ha_prototypes.h +++ b/storage/innobase/include/ha_prototypes.h @@ -269,6 +269,18 @@ innobase_casedn_str( /*================*/ char* a); /*!< in/out: string to put in lower case */ +#ifdef WITH_WSREP +UNIV_INTERN +int +wsrep_innobase_kill_one_trx(const trx_t *bf_trx, trx_t *victim_trx, ibool signal); +int wsrep_thd_is_brute_force(void *thd_ptr); +int wsrep_trx_order_before(void *thd1, void *thd2); +void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, + unsigned char* str, unsigned int str_length); +int +wsrep_on(void *thd_ptr); +int wsrep_is_wsrep_xid(const void*); +#endif /* WITH_WSREP */ /**********************************************************************//** Determines the connection character set. @return connection character set */ diff --git a/storage/innobase/include/lock0lock.h b/storage/innobase/include/lock0lock.h index f97a11b9483..edab4c83876 100644 --- a/storage/innobase/include/lock0lock.h +++ b/storage/innobase/include/lock0lock.h @@ -866,9 +866,7 @@ lock_trx_has_sys_table_locks( record */ #define LOCK_CONV_BY_OTHER 4096 /*!< this bit is set when the lock is created by other transaction */ -#if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_CONV_BY_OTHER)&LOCK_MODE_MASK -# error -#endif +#define WSREP_BF 8192 #if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_CONV_BY_OTHER)&LOCK_TYPE_MASK # error #endif @@ -951,6 +949,16 @@ extern ib_int64_t srv_n_lock_wait_time; extern ulint srv_n_lock_max_wait_time; extern os_event_t srv_lock_timeout_thread_event; +#ifdef WITH_WSREP +/*********************************************************************//** +Cancels a waiting lock request and releases possible other transactions +waiting behind it. */ +UNIV_INTERN +void +lock_cancel_waiting_and_release( +/*============================*/ + lock_t* lock); /*!< in/out: waiting lock request */ +#endif /* WITH_WSREP */ #ifndef UNIV_NONINL #include "lock0lock.ic" #endif diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index 671f8052afa..0daf80b215f 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -840,6 +840,15 @@ are given in one byte (resp. two byte) format. */ two upmost bits in a two byte offset for special purposes */ #define REC_MAX_DATA_SIZE (16 * 1024) +#ifdef WITH_WSREP +int wsrep_rec_get_foreign_key( + byte *buf, /* out: extracted key */ + ulint *buf_len, /* in/out: length of buf */ + const rec_t* rec, /* in: physical record */ + dict_index_t* index_for, /* in: index for foreign table */ + dict_index_t* index_ref, /* in: index for referenced table */ + ibool new_protocol); /* in: protocol > 1 */ +#endif /* WITH_WSREP */ #ifndef UNIV_NONINL #include "rem0rec.ic" #endif diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index 65257baa4bb..8ebbb227264 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -176,6 +176,10 @@ extern ulint srv_log_buffer_size; extern ulong srv_flush_log_at_trx_commit; extern char srv_adaptive_flushing; +#ifdef WITH_INNODB_DISALLOW_WRITES +/* When this event is reset we do not allow any file writes to take place. */ +extern os_event_t srv_allow_writes_event; +#endif /* WITH_INNODB_DISALLOW_WRITES */ /* If this flag is TRUE, then we will load the indexes' (and tables') metadata even if they are marked as "corrupted". Mostly it is for DBA to process corrupted index and table */ @@ -825,5 +829,13 @@ struct srv_slot_struct{ # define srv_start_raw_disk_in_use 0 # define srv_file_per_table 1 #endif /* !UNIV_HOTBACKUP */ +#ifdef WITH_WSREP +UNIV_INTERN +void +wsrep_srv_conc_cancel_wait( +/*==================*/ + trx_t* trx); /*!< in: transaction object associated with the + thread */ +#endif /* WITH_WSREP */ #endif diff --git a/storage/innobase/include/trx0sys.h b/storage/innobase/include/trx0sys.h index b1aa3d2224c..18f3b6ba94a 100644 --- a/storage/innobase/include/trx0sys.h +++ b/storage/innobase/include/trx0sys.h @@ -42,6 +42,9 @@ Created 3/26/1996 Heikki Tuuri #include "read0types.h" #include "page0types.h" #include "ut0bh.h" +#ifdef WITH_WSREP +#include "trx0xa.h" +#endif /* WITH_WSREP */ typedef UT_LIST_BASE_NODE_T(trx_t) trx_list_t; @@ -301,6 +304,17 @@ UNIV_INTERN void trx_sys_print_mysql_binlog_offset(void); /*===================================*/ +#ifdef WITH_WSREP +/** Update WSREP checkpoint XID in sys header. */ +void +trx_sys_update_wsrep_checkpoint( + const XID* xid, /*!< in: WSREP XID */ + mtr_t* mtr); /*!< in: mtr */ +void +/** Read WSREP checkpoint XID from sys header. */ +trx_sys_read_wsrep_checkpoint( + XID* xid); /*!< out: WSREP XID */ +#endif /* WITH_WSREP */ /*****************************************************************//** Prints to stderr the MySQL master log offset info in the trx system header if the magic number shows it valid. */ @@ -529,6 +543,22 @@ this contains the same fields as TRX_SYS_MYSQL_LOG_INFO below */ within that file */ #define TRX_SYS_MYSQL_LOG_NAME 12 /*!< MySQL log file name */ +#ifdef WITH_WSREP +/* We hijack TRX_SYS_MYSQL_MASTER_LOG_INFO, it seems to be completely unused + otherwise (see comments for MySQL bug #34058). */ +/** */ +#define TRX_SYS_WSREP_XID_INFO TRX_SYS_MYSQL_MASTER_LOG_INFO +#define TRX_SYS_WSREP_XID_MAGIC_N_FLD 0 +#define TRX_SYS_WSREP_XID_MAGIC_N 0x77737265 + +/* XID field: formatID, gtrid_len, bqual_len, xid_data */ +#define TRX_SYS_WSREP_XID_LEN (4 + 4 + 4 + XIDDATASIZE) +#define TRX_SYS_WSREP_XID_FORMAT 4 +#define TRX_SYS_WSREP_XID_GTRID_LEN 8 +#define TRX_SYS_WSREP_XID_BQUAL_LEN 12 +#define TRX_SYS_WSREP_XID_DATA 16 +#endif /* WITH_WSREP*/ + /** Doublewrite buffer */ /* @{ */ /** The offset of the doublewrite buffer header on the trx system header page */ diff --git a/storage/innobase/include/trx0trx.h b/storage/innobase/include/trx0trx.h index 3e6cfc7d0da..baeff75a27c 100644 --- a/storage/innobase/include/trx0trx.h +++ b/storage/innobase/include/trx0trx.h @@ -937,6 +937,9 @@ struct trx_struct{ /*------------------------------*/ char detailed_error[256]; /*!< detailed error message for last error, or empty. */ +#ifdef WITH_WSREP + os_event_t wsrep_event; /* event waited for in srv_conc_slot */ +#endif /* WITH_WSREP */ }; /* Transaction isolation levels (trx->isolation_level) */ diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index fff59852704..d493902726b 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -47,6 +47,10 @@ Created 5/7/1996 Heikki Tuuri #include "ut0vec.h" #include "btr0btr.h" +#ifdef WITH_WSREP +extern my_bool wsrep_debug; +extern my_bool wsrep_log_conflicts; +#endif /* Restricts the length of search we will do in the waits-for graph of transactions */ #define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000 @@ -977,6 +981,11 @@ lock_rec_has_to_wait( && !lock_mode_compatible(static_cast<enum lock_mode>( LOCK_MODE_MASK & type_mode), lock_get_mode(lock2))) { +#ifdef WITH_WSREP + if ((type_mode & WSREP_BF) && (lock2->type_mode & WSREP_BF)) { + return FALSE; + } +#endif /* WITH_WSREP */ /* We have somewhat complex rules when gap type record locks cause waits */ @@ -1525,6 +1534,11 @@ lock_rec_has_expl( return(NULL); } +#ifdef WITH_WSREP +static +void +lock_rec_discard(lock_t* in_lock); +#endif #ifdef UNIV_DEBUG /*********************************************************************//** Checks if some other transaction has a lock request in the queue. @@ -1573,6 +1587,54 @@ lock_rec_other_has_expl_req( } #endif /* UNIV_DEBUG */ +#ifdef WITH_WSREP +static void +wsrep_kill_victim(const trx_t *trx, const lock_t *lock) { + int bf_this = wsrep_thd_is_brute_force(trx->mysql_thd); + int bf_other = + wsrep_thd_is_brute_force(lock->trx->mysql_thd); + if ((bf_this && !bf_other) || + (bf_this && bf_other && wsrep_trx_order_before( + trx->mysql_thd, lock->trx->mysql_thd))) { + + if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) { + if (wsrep_debug) + fprintf(stderr, "WSREP: BF victim waiting\n"); + /* cannot release lock, until our lock + is in the queue*/ + } else if (lock->trx != trx) { + if (wsrep_log_conflicts) { + if (bf_this) + fputs("\n*** Priority TRANSACTION:\n", + stderr); + else + fputs("\n*** Victim TRANSACTION:\n", + stderr); + trx_print(stderr, trx, 3000); + + if (bf_other) + fputs("\n*** Priority TRANSACTION:\n", + stderr); + else + fputs("\n*** Victim TRANSACTION:\n", + stderr); + trx_print(stderr, lock->trx, 3000); + + fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n", + stderr); + + if (lock_get_type(lock) == LOCK_REC) { + lock_rec_print(stderr, lock); + } else { + lock_table_print(stderr, lock); + } + } + wsrep_innobase_kill_one_trx( + (const trx_t*)trx, lock->trx, TRUE); + } + } +} +#endif /*********************************************************************//** Checks if some other transaction has a conflicting explicit lock request in the queue, so that we have to wait. @@ -1602,6 +1664,9 @@ lock_rec_other_has_conflicting( lock = lock_rec_get_next_const(heap_no, lock)) { if (lock_rec_has_to_wait(trx, mode, lock, is_supremum)) { +#ifdef WITH_WSREP + wsrep_kill_victim(trx, lock); +#endif return(lock); } } @@ -1739,6 +1804,9 @@ static lock_t* lock_rec_create( /*============*/ +#ifdef WITH_WSREP + lock_t* c_lock, /* conflicting lock */ +#endif ulint type_mode,/*!< in: lock mode and wait flag, type is ignored and replaced by LOCK_REC */ @@ -1791,6 +1859,11 @@ lock_rec_create( lock->trx = trx; lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC; +#ifdef WITH_WSREP + if (wsrep_thd_is_brute_force(trx->mysql_thd)) { + lock->type_mode |= WSREP_BF; + } +#endif /* WITH_WSREP */ lock->index = index; lock->un_member.rec_lock.space = space; @@ -1809,9 +1882,69 @@ lock_rec_create( ut_ad(index->table->n_ref_count > 0 || !index->table->can_be_evicted); +#ifdef WITH_WSREP + if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { + //hash_node_t *hash = c_lock->hash; + lock_t *hash = (lock_t *)c_lock->hash; + lock_t *prev = NULL; + + while (hash && + wsrep_thd_is_brute_force( + ((lock_t *)hash)->trx->mysql_thd) && + wsrep_trx_order_before( + ((lock_t *)hash)->trx->mysql_thd, + trx->mysql_thd)) { + prev = hash; + hash = (lock_t *)hash->hash; + } + lock->hash = hash; + if (prev) { + prev->hash = lock; + } else { + c_lock->hash = lock; + } + /* + * delayed conflict resolution '...kill_one_trx' was not called, + * if victim was waiting for some other lock + */ + if (c_lock && c_lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT){ + c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE; + + if (wsrep_debug && + c_lock->trx->lock.wait_lock != c_lock) { + fprintf(stderr, "WSREP: c_lock != wait lock\n"); + lock_rec_print(stderr, c_lock); + lock_rec_print(stderr, c_lock->trx->lock.wait_lock); + } + + trx->lock.que_state = TRX_QUE_LOCK_WAIT; + lock_set_lock_and_trx_wait(lock, trx); + + lock_cancel_waiting_and_release(c_lock->trx->lock.wait_lock); + + /* trx might not wait for c_lock, but some other lock + does not matter if wait_lock was released above + */ + if (c_lock->trx->lock.wait_lock == c_lock) { + lock_reset_lock_and_trx_wait(lock); + } + + if (wsrep_debug) fprintf( + stderr, + "WSREP: c_lock canceled %llu\n", + (ulonglong) c_lock->trx->id); + + /* have to bail out here to avoid lock_set_lock... */ + return(lock); + } + } else { + HASH_INSERT(lock_t, hash, lock_sys->rec_hash, + lock_rec_fold(space, page_no), lock); + } +#else HASH_INSERT(lock_t, hash, lock_sys->rec_hash, lock_rec_fold(space, page_no), lock); - +#endif if (!caller_owns_trx_mutex) { trx_mutex_enter(trx); } @@ -1845,6 +1978,9 @@ static enum db_err lock_rec_enqueue_waiting( /*=====================*/ +#ifdef WITH_WSREP + lock_t* c_lock, /* conflicting lock */ +#endif ulint type_mode,/*!< in: lock mode this transaction is requesting: LOCK_S or LOCK_X, possibly @@ -1902,9 +2038,20 @@ lock_rec_enqueue_waiting( /* Enqueue the lock request that will wait to be granted, note that we already own the trx mutex. */ +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->lock.was_chosen_as_deadlock_victim) { + return(DB_DEADLOCK); + } + lock = lock_rec_create( + c_lock, + type_mode | LOCK_WAIT, block, heap_no, + index, trx, TRUE); +#else lock = lock_rec_create( type_mode | LOCK_WAIT, block, heap_no, index, trx, TRUE); +#endif /* WITH_WSREP */ } else { ut_ad(lock->type_mode & LOCK_WAIT); ut_ad(lock->type_mode & LOCK_CONV_BY_OTHER); @@ -2010,7 +2157,19 @@ lock_rec_add_to_queue( const lock_t* other_lock = lock_rec_other_has_expl_req(mode, 0, LOCK_WAIT, block, heap_no, trx); +#ifdef WITH_WSREP + /* this can potentionally assert with wsrep */ + if (wsrep_on(trx->mysql_thd)) { + if (wsrep_debug && other_lock) { + fprintf(stderr, + "WSREP: InnoDB assert ignored\n"); + } + } else { + ut_a(!other_lock); + } +#else ut_a(!other_lock); +#endif /* WITH_WSREP */ } #endif /* UNIV_DEBUG */ @@ -2061,9 +2220,15 @@ lock_rec_add_to_queue( } somebody_waits: +#ifdef WITH_WSREP + return(lock_rec_create(NULL, + type_mode, block, heap_no, index, trx, + caller_owns_trx_mutex)); +#else return(lock_rec_create( type_mode, block, heap_no, index, trx, caller_owns_trx_mutex)); +#endif } /** Record locking request status */ @@ -2114,6 +2279,11 @@ lock_rec_lock_fast( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == 0 +#ifdef WITH_WSREP + || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0 + || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP + || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP +#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); lock = lock_rec_get_first_on_page(block); @@ -2123,9 +2293,13 @@ lock_rec_lock_fast( if (lock == NULL) { if (!impl) { /* Note that we don't own the trx mutex. */ +#ifdef WITH_WSREP + lock = lock_rec_create(NULL, + mode, block, heap_no, index, trx, FALSE); +#else lock = lock_rec_create( mode, block, heap_no, index, trx, FALSE); - +#endif } status = LOCK_REC_SUCCESS_CREATED; } else { @@ -2178,6 +2352,9 @@ lock_rec_lock_slow( que_thr_t* thr) /*!< in: query thread */ { trx_t* trx; +#ifdef WITH_WSREP + lock_t *c_lock; +#endif lock_t* lock; enum db_err err = DB_SUCCESS; @@ -2190,6 +2367,11 @@ lock_rec_lock_slow( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == 0 +#ifdef WITH_WSREP + || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0 + || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP + || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP +#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); trx = thr_get_trx(thr); @@ -2220,10 +2402,15 @@ lock_rec_lock_slow( /* The trx already has a strong enough lock on rec: do nothing */ +#ifdef WITH_WSREP + } else if ((c_lock = (lock_t *)lock_rec_other_has_conflicting( + static_cast<enum lock_mode>(mode), + block, heap_no, trx))) { +#else } else if (lock_rec_other_has_conflicting( static_cast<enum lock_mode>(mode), block, heap_no, trx)) { - +#endif /* If another transaction has a non-gap conflicting request in the queue, as this transaction does not have a lock strong enough already granted on the @@ -2231,9 +2418,13 @@ lock_rec_lock_slow( ut_ad(lock == NULL); enqueue_waiting: +#ifdef WITH_WSREP + err = lock_rec_enqueue_waiting(c_lock, + mode, block, heap_no, lock, index, thr); +#else err = lock_rec_enqueue_waiting( mode, block, heap_no, lock, index, thr); - +#endif /* WITH_WSREP */ } else if (!impl) { /* Set the requested lock on the record, note that we already own the transaction mutex. */ @@ -2283,8 +2474,17 @@ lock_rec_lock( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP +#ifdef WITH_WSREP + || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0 + || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP + || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP +#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == 0); - +#ifdef WITH_WSREP + if (wsrep_thd_is_brute_force(thr_get_trx(thr)->mysql_thd)) { + mode |= WSREP_BF; + } +#endif /* We try a simplified and faster subroutine for the most common cases */ switch (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) { @@ -3719,9 +3919,19 @@ lock_deadlock_select_victim( /* The joining transaction is 'smaller', choose it as the victim and roll it back. */ +#ifdef WITH_WSREP + if (wsrep_thd_is_brute_force(ctx->start->mysql_thd)) + return(ctx->wait_lock->trx); + else +#endif /* WITH_WSREP */ return(ctx->start); } +#ifdef WITH_WSREP + if (wsrep_thd_is_brute_force(ctx->wait_lock->trx->mysql_thd)) + return(ctx->start); + else +#endif /* WITH_WSREP */ return(ctx->wait_lock->trx); } @@ -3866,6 +4076,11 @@ lock_deadlock_search( ctx->too_deep = TRUE; /* Select the joining transaction as the victim. */ +#ifdef WITH_WSREP + if (wsrep_thd_is_brute_force(ctx->start->mysql_thd)) + return(ctx->wait_lock->trx->id); + else +#endif /* WITH_WSREP */ return(ctx->start->id); } else if (lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) { @@ -3881,6 +4096,11 @@ lock_deadlock_search( ctx->too_deep = TRUE; +#ifdef WITH_WSREP + if (wsrep_thd_is_brute_force(ctx->start->mysql_thd)) + return(lock->trx->id); + else +#endif /* WITH_WSREP */ return(ctx->start->id); } @@ -4010,10 +4230,18 @@ lock_deadlock_check_and_resolve( if (ctx.too_deep) { ut_a(trx == ctx.start); +#ifdef WITH_WSREP + if (!wsrep_thd_is_brute_force(ctx.start->mysql_thd)) + { +#endif /* WITH_WSREP */ ut_a(victim_trx_id == trx->id); lock_deadlock_joining_trx_print(trx, lock); +#ifdef WITH_WSREP + } else + /* BF processor */; +#endif /* WITH_WSREP */ MONITOR_INC(MONITOR_DEADLOCK); } else if (victim_trx_id != 0 && victim_trx_id != trx->id) { @@ -4050,6 +4278,9 @@ UNIV_INLINE lock_t* lock_table_create( /*==============*/ +#ifdef WITH_WSREP + lock_t* c_lock, /* conflicting lock */ +#endif dict_table_t* table, /*!< in/out: database table in dictionary cache */ ulint type_mode,/*!< in: lock mode possibly ORed with @@ -4095,6 +4326,24 @@ lock_table_create( UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock); UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock); +#ifdef WITH_WSREP + if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { + UT_LIST_INSERT_AFTER( + un_member.tab_lock.locks, table->locks, c_lock, lock); + } else { + UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock); + } + + if (c_lock && c_lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) { + if (wsrep_debug) + fprintf(stderr, "WSREP: table c_lock in wait: %llu\n", + (ulonglong) lock->trx->id); + c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE; + lock_cancel_waiting_and_release(c_lock); + } +#else + UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock); +#endif /* WITH_WSREP */ if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) { @@ -4251,6 +4500,9 @@ static ulint lock_table_enqueue_waiting( /*=======================*/ +#ifdef WITH_WSREP + lock_t* c_lock, /* conflicting lock */ +#endif ulint mode, /*!< in: lock mode this transaction is requesting */ dict_table_t* table, /*!< in/out: table */ @@ -4294,7 +4546,14 @@ lock_table_enqueue_waiting( /* Enqueue the lock request that will wait to be granted */ +#ifdef WITH_WSREP + if (trx->lock.was_chosen_as_deadlock_victim) { + return(DB_DEADLOCK); + } + lock = lock_table_create(c_lock, table, mode | LOCK_WAIT, trx); +#else lock = lock_table_create(table, mode | LOCK_WAIT, trx); +#endif /* Release the mutex to obey the latching order. This is safe, because lock_deadlock_check_and_resolve() @@ -4366,6 +4625,11 @@ lock_table_other_has_incompatible( && !lock_mode_compatible(lock_get_mode(lock), mode) && (wait || !lock_get_wait(lock))) { +#ifdef WITH_WSREP + if (wsrep_debug) + fprintf(stderr, "WSREP: table lock abort"); + wsrep_kill_victim((trx_t *)trx, (lock_t *)lock); +#endif return(lock); } } @@ -4427,9 +4691,18 @@ lock_table( mode: this trx may have to wait */ if (wait_for != NULL) { +#ifdef WITH_WSREP + err = lock_table_enqueue_waiting((lock_t *)wait_for, + mode | flags, table, thr); +#else err = lock_table_enqueue_waiting(mode | flags, table, thr); +#endif /* WITH_WSREP */ } else { +#ifdef WITH_WSREP + lock_table_create((lock_t *)wait_for, table, mode | flags, trx); +#else lock_table_create(table, mode | flags, trx); +#endif /* WITH_WSREP */ ut_a(!flags || mode == LOCK_S || mode == LOCK_X); @@ -5526,6 +5799,7 @@ lock_rec_queue_validate( if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) { +#ifndef WITH_WSREP enum lock_mode mode; if (lock_get_mode(lock) == LOCK_S) { @@ -5535,6 +5809,7 @@ lock_rec_queue_validate( } ut_a(!lock_rec_other_has_expl_req( mode, 0, 0, block, heap_no, lock->trx)); +#endif /* WITH_WSREP */ } else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) { @@ -5830,6 +6105,9 @@ lock_rec_insert_check_and_lock( lock_t* lock; ulint err; ulint next_rec_heap_no; +#ifdef WITH_WSREP + lock_t *c_lock; +#endif ut_ad(block->frame == page_align(rec)); @@ -5885,17 +6163,29 @@ lock_rec_insert_check_and_lock( had to wait for their insert. Both had waiting gap type lock requests on the successor, which produced an unnecessary deadlock. */ +#ifdef WITH_WSREP + if ((c_lock = (lock_t *)lock_rec_other_has_conflicting( + static_cast<enum lock_mode>( + LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION), + block, next_rec_heap_no, trx))) { +#else if (lock_rec_other_has_conflicting( static_cast<enum lock_mode>( LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION), block, next_rec_heap_no, trx)) { - +#endif /* WITH_WSREP */ /* Note that we may get DB_SUCCESS also here! */ trx_mutex_enter(trx); +#ifdef WITH_WSREP + err = lock_rec_enqueue_waiting(c_lock, + LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION, + block, next_rec_heap_no, NULL, index, thr); +#else err = lock_rec_enqueue_waiting( LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION, block, next_rec_heap_no, NULL, index, thr); +#endif /* WITH_WSREP */ trx_mutex_exit(trx); } else { @@ -5996,6 +6286,11 @@ lock_rec_convert_impl_to_expl( implicit lock. Because cannot lock at this moment.*/ if (rec_get_deleted_flag(rec, rec_offs_comp(offsets)) +#ifdef WITH_WSREP + && !wsrep_thd_is_brute_force(impl_trx->mysql_thd) + /* BF-BF conflict is possible if advancing into + lock_rec_other_has_conflicting*/ +#endif /* WITH_WSREP */ && lock_rec_other_has_conflicting( static_cast<enum lock_mode> (LOCK_X | LOCK_REC_NOT_GAP), block, diff --git a/storage/innobase/os/os0file.cc b/storage/innobase/os/os0file.cc index 6d1b3aacf41..acf592a6756 100644 --- a/storage/innobase/os/os0file.cc +++ b/storage/innobase/os/os0file.cc @@ -82,6 +82,12 @@ UNIV_INTERN os_mutex_t os_file_seek_mutexes[OS_FILE_N_SEEK_MUTEXES]; /* In simulated aio, merge at most this many consecutive i/os */ #define OS_AIO_MERGE_N_CONSECUTIVE 64 +#ifdef WITH_INNODB_DISALLOW_WRITES +#define WAIT_ALLOW_WRITES() os_event_wait(srv_allow_writes_event) +#else +#define WAIT_ALLOW_WRITES() do { } while (0) +#endif /* WITH_INNODB_DISALLOW_WRITES */ + /********************************************************************** InnoDB AIO Implementation: @@ -763,7 +769,9 @@ os_file_create_tmpfile(void) /*========================*/ { FILE* file = NULL; - int fd = innobase_mysql_tmpfile(); + int fd; + WAIT_ALLOW_WRITES(); + fd = innobase_mysql_tmpfile(); if (fd >= 0) { file = fdopen(fd, "w+b"); @@ -1084,6 +1092,7 @@ os_file_create_directory( return (TRUE); #else int rcode; + WAIT_ALLOW_WRITES(); rcode = mkdir(pathname, 0770); @@ -1181,6 +1190,8 @@ try_again: os_file_t file; int create_flag; ibool retry; + if (create_mode != OS_FILE_OPEN && create_mode != OS_FILE_OPEN_RAW) + WAIT_ALLOW_WRITES(); ut_a(!(create_mode & OS_FILE_ON_ERROR_SILENT)); ut_a(!(create_mode & OS_FILE_ON_ERROR_NO_EXIT)); @@ -1316,6 +1327,8 @@ os_file_create_simple_no_error_handling_func( int create_flag; ut_a(name); + if (create_mode != OS_FILE_OPEN && create_mode != OS_FILE_OPEN_RAW) + WAIT_ALLOW_WRITES(); ut_a(!(create_mode & OS_FILE_ON_ERROR_SILENT)); ut_a(!(create_mode & OS_FILE_ON_ERROR_NO_EXIT)); @@ -1601,6 +1614,8 @@ try_again: int create_flag; ibool retry; const char* mode_str = NULL; + if (create_mode != OS_FILE_OPEN && create_mode != OS_FILE_OPEN_RAW) + WAIT_ALLOW_WRITES(); on_error_no_exit = create_mode & OS_FILE_ON_ERROR_NO_EXIT ? TRUE : FALSE; @@ -1772,6 +1787,7 @@ loop: goto loop; #else int ret; + WAIT_ALLOW_WRITES(); ret = unlink(name); @@ -1836,6 +1852,7 @@ loop: goto loop; #else int ret; + WAIT_ALLOW_WRITES(); ret = unlink(name); @@ -1876,6 +1893,7 @@ os_file_rename_func( return(FALSE); #else int ret; + WAIT_ALLOW_WRITES(); ret = rename(oldpath, newpath); @@ -2109,6 +2127,7 @@ os_file_set_eof( HANDLE h = (HANDLE) _get_osfhandle(fileno(file)); return(SetEndOfFile(h)); #else /* __WIN__ */ + WAIT_ALLOW_WRITES(); return(!ftruncate(fileno(file), ftell(file))); #endif /* __WIN__ */ } @@ -2203,6 +2222,7 @@ os_file_flush_func( return(FALSE); #else int ret; + WAIT_ALLOW_WRITES(); #if defined(HAVE_DARWIN_THREADS) # ifndef F_FULLFSYNC @@ -2887,6 +2907,7 @@ retry: return(FALSE); #else ssize_t ret; + WAIT_ALLOW_WRITES(); ret = os_file_pwrite(file, buf, n, offset); diff --git a/storage/innobase/rem/rem0rec.cc b/storage/innobase/rem/rem0rec.cc index d56eb59e0bb..5ef5dd3ebe5 100644 --- a/storage/innobase/rem/rem0rec.cc +++ b/storage/innobase/rem/rem0rec.cc @@ -32,6 +32,9 @@ Created 5/30/1994 Heikki Tuuri #include "mtr0mtr.h" #include "mtr0log.h" #include "fts0fts.h" +#ifdef WITH_WSREP +#include <ha_prototypes.h> +#endif /* WITH_WSREP */ /* PHYSICAL RECORD (OLD STYLE) =========================== @@ -1907,3 +1910,133 @@ rec_print( } } #endif /* !UNIV_HOTBACKUP */ +#ifdef WITH_WSREP +int +wsrep_rec_get_foreign_key( + byte *buf, /* out: extracted key */ + ulint *buf_len, /* in/out: length of buf */ + const rec_t* rec, /* in: physical record */ + dict_index_t* index_for, /* in: index in foreign table */ + dict_index_t* index_ref, /* in: index in referenced table */ + ibool new_protocol) /* in: protocol > 1 */ +{ + const byte* data; + ulint len; + ulint key_len = 0; + ulint i; + uint key_parts; + mem_heap_t* heap = NULL; + ulint offsets_[REC_OFFS_NORMAL_SIZE]; + const ulint* offsets; + + ut_ad(index_for); + ut_ad(index_ref); + + rec_offs_init(offsets_); + offsets = rec_get_offsets(rec, index_for, offsets_, + ULINT_UNDEFINED, &heap); + + ut_ad(rec_offs_validate(rec, NULL, offsets)); + + ut_ad(rec); + + key_parts = dict_index_get_n_unique_in_tree(index_for); + for (i = 0; + i < key_parts && + (index_for->type & DICT_CLUSTERED || i < key_parts - 1); + i++) { + dict_field_t* field_f = + dict_index_get_nth_field(index_for, i); + const dict_col_t* col_f = dict_field_get_col(field_f); + dict_field_t* field_r = + dict_index_get_nth_field(index_ref, i); + const dict_col_t* col_r = dict_field_get_col(field_r); + + data = rec_get_nth_field(rec, offsets, i, &len); + if (key_len + ((len != UNIV_SQL_NULL) ? len + 1 : 1) > + *buf_len) { + fprintf (stderr, + "WSREP: FK key len exceeded %lu %lu %lu\n", + key_len, len, *buf_len); + goto err_out; + } + + if (len == UNIV_SQL_NULL) { + ut_a(!(col_f->prtype & DATA_NOT_NULL)); + *buf++ = 1; + key_len++; + } else if (!new_protocol) { + if (!(col_r->prtype & DATA_NOT_NULL)) { + *buf++ = 0; + key_len++; + } + memcpy(buf, data, len); + wsrep_innobase_mysql_sort( + (int)(col_f->prtype & DATA_MYSQL_TYPE_MASK), + (uint)dtype_get_charset_coll(col_f->prtype), + buf, len); + } else { /* new protocol */ + if (!(col_r->prtype & DATA_NOT_NULL)) { + *buf++ = 0; + key_len++; + } + switch (col_f->mtype) { + case DATA_INT: { + byte* ptr = buf+len; + for (;;) { + ptr--; + *ptr = *data; + if (ptr == buf) { + break; + } + data++; + } + + if (!(col_f->prtype & DATA_UNSIGNED)) { + buf[len-1] = (byte) (buf[len-1] ^ 128); + } + + break; + } + case DATA_VARCHAR: + case DATA_VARMYSQL: + case DATA_CHAR: + case DATA_MYSQL: + /* Copy the actual data */ + ut_memcpy(buf, data, len); + wsrep_innobase_mysql_sort( + (int) + (col_f->prtype & DATA_MYSQL_TYPE_MASK), + (uint) + dtype_get_charset_coll(col_f->prtype), + buf, len); + break; + case DATA_BLOB: + case DATA_BINARY: + memcpy(buf, data, len); + break; + default: + break; + } + + key_len += len; + buf += len; + } + } + + rec_validate(rec, offsets); + + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } + + *buf_len = key_len; + return DB_SUCCESS; + + err_out: + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } + return DB_ERROR; +} +#endif // WITH_WSREP diff --git a/storage/innobase/row/row0ins.cc b/storage/innobase/row/row0ins.cc index e8d15fb539c..a6fd166da6f 100644 --- a/storage/innobase/row/row0ins.cc +++ b/storage/innobase/row/row0ins.cc @@ -873,6 +873,14 @@ row_ins_invalidate_query_cache( innobase_invalidate_query_cache(thr_get_trx(thr), buf, len); mem_free(buf); } +#ifdef WITH_WSREP +ulint wsrep_append_foreign_key(trx_t *trx, + dict_foreign_t* foreign, + const rec_t* clust_rec, + dict_index_t* clust_index, + ibool referenced, + ibool shared); +#endif /* WITH_WSREP */ /*********************************************************************//** Perform referential actions or checks when a parent row is deleted or updated @@ -1227,6 +1235,16 @@ row_ins_foreign_check_on_constraint( err = row_update_cascade_for_mysql(thr, cascade, foreign->foreign_table); +#ifdef WITH_WSREP + if (err == DB_SUCCESS) { + err = wsrep_append_foreign_key( + thr_get_trx(thr), + foreign, + clust_rec, + clust_index, + FALSE, FALSE); + } +#endif /* WITH_WSREP */ if (foreign->foreign_table->n_foreign_key_checks_running == 0) { fprintf(stderr, "InnoDB: error: table %s has the counter 0" @@ -1551,7 +1569,14 @@ run_again: if (check_ref) { err = DB_SUCCESS; - +#ifdef WITH_WSREP + err = wsrep_append_foreign_key( + thr_get_trx(thr), + foreign, + rec, + check_index, + check_ref, TRUE); +#endif /* WITH_WSREP */ goto end_scan; } else if (foreign->type != 0) { /* There is an ON UPDATE or ON DELETE @@ -1802,6 +1827,9 @@ row_ins_scan_sec_index_for_duplicate( dtuple_t* entry, /*!< in: index entry */ que_thr_t* thr) /*!< in: query thread */ { +#ifdef WITH_WSREP + trx_t* trx = thr_get_trx(thr); +#endif ulint n_unique; ulint i; int cmp; @@ -1855,7 +1883,14 @@ row_ins_scan_sec_index_for_duplicate( offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); +#ifdef WITH_WSREP + /* slave applier must not get duplicate error */ + if (allow_duplicates || + (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd))) { +#else if (allow_duplicates) { +#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for @@ -1973,7 +2008,13 @@ row_ins_duplicate_error_in_clust( sure that in roll-forward we get the same duplicate errors as in original execution */ +#ifdef WITH_WSREP + if (trx->duplicates || + (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd))) { +#else if (trx->duplicates) { +#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for @@ -2017,7 +2058,13 @@ row_ins_duplicate_error_in_clust( offsets = rec_get_offsets(rec, cursor->index, offsets, ULINT_UNDEFINED, &heap); +#ifdef WITH_WSREP + if (trx->duplicates || + (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd))) { +#else if (trx->duplicates) { +#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for diff --git a/storage/innobase/row/row0upd.cc b/storage/innobase/row/row0upd.cc index 28faa59add8..fc391300a8c 100644 --- a/storage/innobase/row/row0upd.cc +++ b/storage/innobase/row/row0upd.cc @@ -51,6 +51,9 @@ Created 12/27/1996 Heikki Tuuri #include "pars0sym.h" #include "eval0eval.h" #include "buf0lru.h" +#ifdef WITH_WSREP +extern my_bool wsrep_debug; +#endif /* What kind of latch and lock can we assume when the control comes to @@ -170,6 +173,16 @@ func_exit: return(is_referenced); } +#ifdef WITH_WSREP +ulint wsrep_append_foreign_key(trx_t *trx, + dict_foreign_t* foreign, + const rec_t* clust_rec, + dict_index_t* clust_index, + ibool referenced, + ibool shared); + +#endif /* WITH_WSREP */ + /*********************************************************************//** Checks if possible foreign key constraints hold after a delete of the record under pcur. @@ -281,7 +294,123 @@ row_upd_check_references_constraints( } err = DB_SUCCESS; +func_exit: + if (got_s_lock) { + row_mysql_unfreeze_data_dictionary(trx); + } + + mem_heap_free(heap); + + return(err); +} +#ifdef WITH_WSREP +static +ulint +wsrep_row_upd_check_foreign_constraints( +/*=================================*/ + upd_node_t* node, /*!< in: row update node */ + btr_pcur_t* pcur, /*!< in: cursor positioned on a record; NOTE: the + cursor position is lost in this function! */ + dict_table_t* table, /*!< in: table in question */ + dict_index_t* index, /*!< in: index of the cursor */ + ulint* offsets,/*!< in/out: rec_get_offsets(pcur.rec, index) */ + que_thr_t* thr, /*!< in: query thread */ + mtr_t* mtr) /*!< in: mtr */ +{ + dict_foreign_t* foreign; + mem_heap_t* heap; + dtuple_t* entry; + trx_t* trx; + const rec_t* rec; + ulint n_ext; + ulint err; + ibool got_s_lock = FALSE; + + if (UT_LIST_GET_FIRST(table->foreign_list) == NULL) { + + return(DB_SUCCESS); + } + + trx = thr_get_trx(thr); + + rec = btr_pcur_get_rec(pcur); + ut_ad(rec_offs_validate(rec, index, offsets)); + + heap = mem_heap_create(500); + + entry = row_rec_to_index_entry(ROW_COPY_DATA, rec, index, offsets, + &n_ext, heap); + + mtr_commit(mtr); + + mtr_start(mtr); + + if (trx->dict_operation_lock_mode == 0) { + got_s_lock = TRUE; + + row_mysql_freeze_data_dictionary(trx); + } + + foreign = UT_LIST_GET_FIRST(table->foreign_list); + while (foreign) { + /* Note that we may have an update which updates the index + record, but does NOT update the first fields which are + referenced in a foreign key constraint. Then the update does + NOT break the constraint. */ + + if (foreign->foreign_index == index + && (node->is_delete + || row_upd_changes_first_fields_binary( + entry, index, node->update, + foreign->n_fields))) { + + if (foreign->referenced_table == NULL) { + foreign->referenced_table = + dict_table_open_on_name( + foreign->referenced_table_name_lookup, + FALSE); + } + + if (foreign->referenced_table) { + mutex_enter(&(dict_sys->mutex)); + + (foreign->referenced_table + ->n_foreign_key_checks_running)++; + + mutex_exit(&(dict_sys->mutex)); + } + + /* 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 'foreign' from + being dropped while the check is running. */ + + err = row_ins_check_foreign_constraint( + TRUE, foreign, table, entry, thr); + + if (foreign->referenced_table) { + mutex_enter(&(dict_sys->mutex)); + + ut_a(foreign->referenced_table + ->n_foreign_key_checks_running > 0); + + (foreign->referenced_table + ->n_foreign_key_checks_running)--; + + mutex_exit(&(dict_sys->mutex)); + } + + if (err != DB_SUCCESS) { + + goto func_exit; + } + } + + foreign = UT_LIST_GET_NEXT(foreign_list, foreign); + } + + err = DB_SUCCESS; func_exit: if (got_s_lock) { row_mysql_unfreeze_data_dictionary(trx); @@ -291,6 +420,7 @@ func_exit: return(err); } +#endif /* WITH_WSREP */ /*********************************************************************//** Creates an update node for a query graph. @@ -1752,6 +1882,33 @@ row_upd_sec_index_entry( node, &pcur, index->table, index, offsets, thr, &mtr); } +#ifdef WITH_WSREP + if (err == DB_SUCCESS && !referenced) { + ulint* offsets = + rec_get_offsets( + rec, index, NULL, ULINT_UNDEFINED, + &heap); + err = wsrep_row_upd_check_foreign_constraints( + node, &pcur, index->table, + index, offsets, thr, &mtr); + switch (err) { + case DB_SUCCESS: + case DB_NO_REFERENCED_ROW: + err = DB_SUCCESS; + break; + case DB_DEADLOCK: + if (wsrep_debug) + fprintf (stderr, + "WSREP: sec index FK check fail for deadlock"); + break; + default: + fprintf (stderr, + "WSREP: referenced FK check fail: %lu", + err); + break; + } + } +#endif /* WITH_WSREP */ } break; } @@ -1995,6 +2152,30 @@ err_exit: goto err_exit; } } +#ifdef WITH_WSREP + if (!referenced) { + err = wsrep_row_upd_check_foreign_constraints( + node, pcur, table, index, offsets, thr, mtr); + switch (err) { + case DB_SUCCESS: + case DB_NO_REFERENCED_ROW: + err = DB_SUCCESS; + break; + case DB_DEADLOCK: + if (wsrep_debug) fprintf (stderr, + "WSREP: insert FK check fail for deadlock"); + break; + default: + fprintf (stderr, + "WSREP: referenced FK check fail: %lu", + err); + break; + } + if (err != DB_SUCCESS) { + goto err_exit; + } + } +#endif /* WITH_WSREP */ } mtr_commit(mtr); @@ -2197,6 +2378,9 @@ row_upd_del_mark_clust_rec( btr_pcur_t* pcur; btr_cur_t* btr_cur; ulint err; +#ifdef WITH_WSREP + rec_t* rec; +#endif /* WITH_WSREP */ ut_ad(node); ut_ad(dict_index_is_clust(index)); @@ -2213,15 +2397,44 @@ row_upd_del_mark_clust_rec( /* Mark the clustered index record deleted; we do not have to check locks, because we assume that we have an x-lock on the record */ +#ifdef WITH_WSREP + rec = btr_cur_get_rec(btr_cur); +#endif /* WITH_WSREP */ + err = btr_cur_del_mark_set_clust_rec( BTR_NO_LOCKING_FLAG, btr_cur_get_block(btr_cur), +#ifdef WITH_WSREP + rec, index, offsets, TRUE, thr, mtr); +#else btr_cur_get_rec(btr_cur), index, offsets, TRUE, thr, mtr); +#endif /* WITH_WSREP */ if (err == DB_SUCCESS && referenced) { /* NOTE that the following call loses the position of pcur ! */ err = row_upd_check_references_constraints( node, pcur, index->table, index, offsets, thr, mtr); } +#ifdef WITH_WSREP + if (err == DB_SUCCESS && !referenced) { + err = wsrep_row_upd_check_foreign_constraints( + node, pcur, index->table, index, offsets, thr, mtr); + switch (err) { + case DB_SUCCESS: + case DB_NO_REFERENCED_ROW: + err = DB_SUCCESS; + break; + case DB_DEADLOCK: + if (wsrep_debug) fprintf (stderr, + "WSREP: clust rec FK check fail for deadlock"); + break; + default: + fprintf (stderr, + "WSREP: clust rec referenced FK check fail: %lu", + err); + break; + } + } +#endif /* WITH_WSREP */ mtr_commit(mtr); diff --git a/storage/innobase/srv/srv0conc.cc b/storage/innobase/srv/srv0conc.cc index d5c949f3a06..6c50e2fe817 100644 --- a/storage/innobase/srv/srv0conc.cc +++ b/storage/innobase/srv/srv0conc.cc @@ -43,6 +43,10 @@ Created 2011/04/18 Sunny Bains #include "ha_prototypes.h" #include "mysql/plugin.h" +#ifdef WITH_WSREP +extern "C" int wsrep_trx_is_aborting(void *thd_ptr); +extern my_bool wsrep_debug; +#endif /** Number of times a thread is allowed to enter InnoDB within the same SQL query after it has once got the ticket. */ @@ -89,6 +93,9 @@ struct srv_conc_slot_struct{ reserved may still be TRUE at that point */ srv_conc_node_t srv_conc_queue; /*!< queue node */ +#ifdef WITH_WSREP + void *thd; /*!< to see priority */ +#endif }; /** Queue of threads waiting to get in */ @@ -150,6 +157,9 @@ srv_conc_init(void) conc_slot->event = os_event_create(NULL); ut_a(conc_slot->event); +#ifdef WITH_WSREP + conc_slot->thd = NULL; +#endif /* WITH_WSREP */ } #endif /* !HAVE_ATOMIC_BUILTINS */ } @@ -250,6 +260,21 @@ srv_conc_enter_innodb_with_atomics( (void) os_atomic_decrement_lint( &srv_conc.n_active, 1); } +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd)) { + srv_conc_force_enter_innodb(trx); + return; + } + if (wsrep_on(trx->mysql_thd) && + wsrep_trx_is_aborting(trx->mysql_thd)) { + if (wsrep_debug) + fprintf(stderr, + "srv_conc_enter due to MUST_ABORT"); + srv_conc_force_enter_innodb(trx); + return; + } +#endif if (!notified_mysql) { (void) os_atomic_increment_lint( @@ -328,6 +353,9 @@ srv_conc_exit_innodb_without_atomics( slot = NULL; if (srv_conc.n_active < (lint) srv_thread_concurrency) { +#ifdef WITH_WSREP + srv_conc_slot_t* wsrep_slot; +#endif /* Look for a slot where a thread is waiting and no other thread has yet released the thread */ @@ -338,6 +366,19 @@ srv_conc_exit_innodb_without_atomics( /* No op */ } +#ifdef WITH_WSREP + /* look for aborting trx, they must be released asap */ + wsrep_slot= slot; + while (wsrep_slot && (wsrep_slot->wait_ended == TRUE || + !wsrep_trx_is_aborting(wsrep_slot->thd))) { + wsrep_slot = UT_LIST_GET_NEXT(srv_conc_queue, wsrep_slot); + } + if (wsrep_slot) { + slot = wsrep_slot; + if (wsrep_debug) + fprintf(stderr, "WSREP: releasing aborting thd\n"); + } +#endif if (slot != NULL) { slot->wait_ended = TRUE; @@ -393,6 +434,18 @@ retry: return; } +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd)) { + srv_conc_force_enter_innodb(trx); + return; + } + if (wsrep_on(trx->mysql_thd) && + wsrep_trx_is_aborting(trx->mysql_thd)) { + srv_conc_force_enter_innodb(trx); + return; + } +#endif /* If the transaction is not holding resources, let it sleep for srv_thread_sleep_delay microseconds, and try again then */ @@ -459,6 +512,9 @@ retry: /* Add to the queue */ slot->reserved = TRUE; slot->wait_ended = FALSE; +#ifdef WITH_WSREP + slot->thd = trx->mysql_thd; +#endif UT_LIST_ADD_LAST(srv_conc_queue, srv_conc_queue, slot); @@ -466,6 +522,19 @@ retry: srv_conc.n_waiting++; +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + wsrep_trx_is_aborting(trx->mysql_thd)) { + srv_conc_n_waiting_threads--; + os_fast_mutex_unlock(&srv_conc_mutex); + if (wsrep_debug) + fprintf(stderr, "srv_conc_enter due to MUST_ABORT"); + trx->declared_to_be_inside_innodb = TRUE; + trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER; + return; + } + trx->wsrep_event = slot->event; +#endif /* WITH_WSREP */ os_fast_mutex_unlock(&srv_conc_mutex); /* Go to wait for the event; when a thread leaves InnoDB it will @@ -480,6 +549,9 @@ retry: thd_wait_begin(static_cast<THD*>(trx->mysql_thd), THD_WAIT_USER_LOCK); os_event_wait(slot->event); +#ifdef WITH_WSREP + trx->wsrep_event = NULL; +#endif /* WITH_WSREP */ thd_wait_end(static_cast<THD*>(trx->mysql_thd)); trx->op_info = ""; @@ -492,6 +564,9 @@ retry: incremented the thread counter on behalf of this thread */ slot->reserved = FALSE; +#ifdef WITH_WSREP + slot->thd = NULL; +#endif UT_LIST_REMOVE(srv_conc_queue, srv_conc_queue, slot); @@ -501,6 +576,39 @@ retry: os_fast_mutex_unlock(&srv_conc_mutex); } #endif /* HAVE_ATOMIC_BUILTINS */ +#ifdef WITH_WSREP +#ifdef HAVE_ATOMIC_BUILTINS +UNIV_INTERN +void +wsrep_srv_conc_cancel_wait( +/*==================*/ + trx_t* trx) /*!< in: transaction object associated with the + thread */ +{ + if (trx->wsrep_event) { + if (wsrep_debug) + fprintf(stderr, "WSREP: conc slot cancel\n"); + os_event_set(trx->wsrep_event); + } +} +#else +UNIV_INTERN +void +wsrep_srv_conc_cancel_wait( +/*==================*/ + trx_t* trx) /*!< in: transaction object associated with the + thread */ +{ + os_fast_mutex_lock(&srv_conc_mutex); + if (trx->wsrep_event) { + if (wsrep_debug) + fprintf(stderr, "WSREP: conc slot cancel\n"); + os_event_set(trx->wsrep_event); + } + os_fast_mutex_unlock(&srv_conc_mutex); +} +#endif /* HAVE_ATOMIC_BUILTINS */ +#endif /* WITH_WSREP */ /*********************************************************************//** Puts an OS thread to wait if there are too many concurrent threads diff --git a/storage/innobase/srv/srv0srv.cc b/storage/innobase/srv/srv0srv.cc index 30e0698eab9..f5f3600cf82 100644 --- a/storage/innobase/srv/srv0srv.cc +++ b/storage/innobase/srv/srv0srv.cc @@ -72,6 +72,10 @@ Created 10/8/1995 Heikki Tuuri #include "mysql/plugin.h" #include "mysql/service_thd_wait.h" +#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; @@ -198,6 +202,10 @@ srv_printf_innodb_monitor() will request mutex acquisition with mutex_enter(), which will wait until it gets the mutex. */ #define MUTEX_NOWAIT(mutex_skipped) ((mutex_skipped) < MAX_MUTEX_NOWAIT) +#ifdef WITH_INNODB_DISALLOW_WRITES +UNIV_INTERN os_event_t srv_allow_writes_event; +#endif /* WITH_INNODB_DISALLOW_WRITES */ + /** The sort order table of the MySQL latin1_swedish_ci character set collation */ UNIV_INTERN const byte* srv_latin1_ordering; @@ -971,6 +979,14 @@ srv_init(void) dict_ind_init(); srv_conc_init(); +#ifdef WITH_INNODB_DISALLOW_WRITES + /* Writes have to be enabled on init or else we hang. Thus, we + always set the event here regardless of innobase_disallow_writes. + That flag will always be 0 at this point because it isn't settable + via my.cnf or command line arg. */ + srv_allow_writes_event = os_event_create(NULL); + os_event_set(srv_allow_writes_event); +#endif /* WITH_INNODB_DISALLOW_WRITES */ /* Initialize some INFORMATION SCHEMA internal structures */ trx_i_s_cache_init(trx_i_s_cache); @@ -1655,7 +1671,20 @@ loop: if (sync_array_print_long_waits(&waiter, &sema) && sema == old_sema && os_thread_eq(waiter, old_waiter)) { +#if defined(WITH_WSREP) && defined(WITH_INNODB_DISALLOW_WRITES) + if (srv_allow_writes_event->is_set) { +#endif /* WITH_WSREP */ fatal_cnt++; +#if defined(WITH_WSREP) && defined(WITH_INNODB_DISALLOW_WRITES) + } else { + fprintf(stderr, + "WSREP: avoiding InnoDB self crash due to long " + "semaphore wait of > %lu seconds\n" + "Server is processing SST donor operation, " + "fatal_cnt now: %lu", + (ulong) srv_fatal_semaphore_wait_threshold, fatal_cnt); + } +#endif /* WITH_WSREP */ if (fatal_cnt > 10) { fprintf(stderr, @@ -2199,6 +2228,27 @@ srv_master_sleep(void) srv_main_thread_op_info = ""; } +#ifdef WITH_WSREP +/*********************************************************************//** +check if lock timeout was for priority thread, +as a side effect trigger lock monitor +@return false for regular lock timeout */ +static ibool +wsrep_is_BF_lock_timeout( +/*====================*/ + srv_slot_t* slot) /* in: lock slot to check for lock priority */ +{ + if (wsrep_on(thr_get_trx(slot->thr)->mysql_thd) && + wsrep_thd_is_brute_force((thr_get_trx(slot->thr))->mysql_thd)) { + fprintf(stderr, "WSREP: BF lock wait long\n"); + srv_print_innodb_monitor = TRUE; + srv_print_innodb_lock_monitor = TRUE; + os_event_set(srv_lock_timeout_thread_event); + return TRUE; + } + return FALSE; + } +#endif /* WITH_WSREP */ /*********************************************************************//** The master thread controlling the server. @return a dummy parameter */ @@ -2277,6 +2327,27 @@ suspend_thread: OS_THREAD_DUMMY_RETURN; /* Not reached, avoid compiler warning */ } +#ifdef WITH_WSREP_TODO +/*********************************************************************//** +check if lock timeout was for priority thread, +as a side effect trigger lock monitor +@return false for regular lock timeout */ +static ibool +wsrep_is_BF_lock_timeout( +/*====================*/ + srv_slot_t* slot) /* in: lock slot to check for lock priority */ +{ + if (wsrep_on(thr_get_trx(slot->thr)->mysql_thd) && + wsrep_thd_is_brute_force((thr_get_trx(slot->thr))->mysql_thd)) { + fprintf(stderr, "WSREP: BF lock wait long\n"); + srv_print_innodb_monitor = TRUE; + srv_print_innodb_lock_monitor = TRUE; + os_event_set(srv_lock_timeout_thread_event); + return TRUE; + } + return FALSE; + } +#endif /* WITH_WSREP */ /*********************************************************************//** Check if purge should stop. @return true if it should shutdown. */ diff --git a/storage/innobase/trx/trx0roll.cc b/storage/innobase/trx/trx0roll.cc index 042b5b87da7..74167a29aa1 100644 --- a/storage/innobase/trx/trx0roll.cc +++ b/storage/innobase/trx/trx0roll.cc @@ -43,6 +43,9 @@ Created 3/26/1996 Heikki Tuuri #include "row0mysql.h" #include "lock0lock.h" #include "pars0pars.h" +#ifdef WITH_WSREP +#include "ha_prototypes.h" +#endif /* WITH_WSREP */ #include "srv0mon.h" #include "trx0sys.h" @@ -382,6 +385,12 @@ trx_rollback_to_savepoint_for_mysql_low( trx->op_info = ""; +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->lock.was_chosen_as_deadlock_victim) { + trx->lock.was_chosen_as_deadlock_victim = FALSE; + } +#endif return(err); } @@ -1018,6 +1027,12 @@ trx_roll_try_truncate( if (trx->update_undo) { trx_undo_truncate_end(trx, trx->update_undo, limit); } +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->lock.was_chosen_as_deadlock_victim) { + trx->lock.was_chosen_as_deadlock_victim = FALSE; + } +#endif } /***********************************************************************//** @@ -1323,6 +1338,12 @@ trx_rollback_finish( trx_commit(trx); trx->lock.que_state = TRX_QUE_RUNNING; +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->lock.was_chosen_as_deadlock_victim) { + trx->lock.was_chosen_as_deadlock_victim = FALSE; + } +#endif } /*********************************************************************//** diff --git a/storage/innobase/trx/trx0sys.cc b/storage/innobase/trx/trx0sys.cc index 97fd1f36943..a36328ed43f 100644 --- a/storage/innobase/trx/trx0sys.cc +++ b/storage/innobase/trx/trx0sys.cc @@ -45,6 +45,10 @@ Created 3/26/1996 Heikki Tuuri #include "read0read.h" #include "buf0dblwr.h" +#ifdef WITH_WSREP +#include "ha_prototypes.h" /* wsrep_is_wsrep_xid() */ +#endif /* */ + /** The file format tag structure with id and name. */ struct file_format_struct { ulint id; /*!< id of the file format */ @@ -300,6 +304,89 @@ trx_sys_print_mysql_binlog_offset(void) mtr_commit(&mtr); } +#ifdef WITH_WSREP + +void +trx_sys_update_wsrep_checkpoint( + const XID* xid, /*!< in: transaction XID */ + mtr_t* mtr) /*!< in: mtr */ +{ + trx_sysf_t* sys_header; + + ut_ad(xid && mtr); + ut_a(xid->formatID == -1 || wsrep_is_wsrep_xid(xid)); + + sys_header = trx_sysf_get(mtr); + if (mach_read_from_4(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_MAGIC_N_FLD) + != TRX_SYS_WSREP_XID_MAGIC_N) { + mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_MAGIC_N_FLD, + TRX_SYS_WSREP_XID_MAGIC_N, + MLOG_4BYTES, mtr); + } + + mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_FORMAT, + (int)xid->formatID, + MLOG_4BYTES, mtr); + mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_GTRID_LEN, + (int)xid->gtrid_length, + MLOG_4BYTES, mtr); + mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_BQUAL_LEN, + (int)xid->bqual_length, + MLOG_4BYTES, mtr); + mlog_write_string(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_DATA, + (const unsigned char*) xid->data, + XIDDATASIZE, mtr); + +} + +void +trx_sys_read_wsrep_checkpoint(XID* xid) +/*===================================*/ +{ + trx_sysf_t* sys_header; + mtr_t mtr; + ulint magic; + + ut_ad(xid); + + mtr_start(&mtr); + + sys_header = trx_sysf_get(&mtr); + + if ((magic = mach_read_from_4(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_MAGIC_N_FLD)) + != TRX_SYS_WSREP_XID_MAGIC_N) { + memset(xid, 0, sizeof(*xid)); + xid->formatID = -1; + trx_sys_update_wsrep_checkpoint(xid, &mtr); + mtr_commit(&mtr); + return; + } + + xid->formatID = (int)mach_read_from_4( + sys_header + + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_FORMAT); + xid->gtrid_length = (int)mach_read_from_4( + sys_header + + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_GTRID_LEN); + xid->bqual_length = (int)mach_read_from_4( + sys_header + + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_BQUAL_LEN); + ut_memcpy(xid->data, + sys_header + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_DATA, + XIDDATASIZE); + + mtr_commit(&mtr); +} + +#endif /* WITH_WSREP */ + /*****************************************************************//** Prints to stderr the MySQL master log offset info in the trx system header if the magic number shows it valid. */ diff --git a/storage/innobase/trx/trx0trx.cc b/storage/innobase/trx/trx0trx.cc index 80ebe0df2b3..a8d40d0cba3 100644 --- a/storage/innobase/trx/trx0trx.cc +++ b/storage/innobase/trx/trx0trx.cc @@ -146,7 +146,10 @@ trx_create(void) trx->lock.table_locks = ib_vector_create( heap_alloc, sizeof(void**), 32); - /* For non-locking selects we avoid calling ut_time() too frequently. +#ifdef WITH_WSREP + trx->wsrep_event = NULL; +#endif /* WITH_WSREP */ + /* For non-locking selects we avoid calling ut_time() too frequently. Set the time here for new transactions. */ trx->start_time = ut_time(); @@ -705,6 +708,11 @@ trx_start_low( trx->start_time = ut_time(); } +#ifdef WITH_WSREP + memset(&trx->xid, 0, sizeof(trx->xid)); + trx->xid.formatID = -1; +#endif /* WITH_WSREP */ + /* The initial value for trx->no: IB_ULONGLONG_MAX is used in read_view_open_now: */ @@ -862,6 +870,14 @@ trx_write_serialisation_history( MONITOR_INC(MONITOR_TRX_COMMIT_UNDO); +#ifdef WITH_WSREP + /* Update latest MySQL wsrep XID in trx sys header. */ + if (wsrep_is_wsrep_xid(&trx->xid)) + { + trx_sys_update_wsrep_checkpoint(&trx->xid, &mtr); + } +#endif /* WITH_WSREP */ + /* Update the latest MySQL binlog name and offset info in trx sys header if MySQL binlogging is on or the database server is a MySQL replication slave */ @@ -1175,6 +1191,12 @@ trx_commit( ut_ad(!trx->in_ro_trx_list); ut_ad(!trx->in_rw_trx_list); +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->lock.was_chosen_as_deadlock_victim) { + trx->lock.was_chosen_as_deadlock_victim = FALSE; + } +#endif trx->error_state = DB_SUCCESS; /* trx->in_mysql_trx_list would hold between @@ -1267,6 +1289,10 @@ trx_commit_or_rollback_prepare( switch (trx->state) { case TRX_STATE_NOT_STARTED: +#ifdef WITH_WSREP + ut_d(trx->start_file = __FILE__); + ut_d(trx->start_line = __LINE__); +#endif /* WITH_WSREP */ trx_start_low(trx); /* fall through */ case TRX_STATE_ACTIVE: @@ -2041,6 +2067,10 @@ trx_start_if_not_started_xa( transaction, doesn't. */ trx->support_xa = thd_supports_xa(trx->mysql_thd); +#ifdef WITH_WSREP + ut_d(trx->start_file = __FILE__); + ut_d(trx->start_line = __LINE__); +#endif /* WITH_WSREP */ trx_start_low(trx); /* fall through */ case TRX_STATE_ACTIVE: @@ -2063,6 +2093,10 @@ trx_start_if_not_started( { switch (trx->state) { case TRX_STATE_NOT_STARTED: +#ifdef WITH_WSREP + ut_d(trx->start_file = __FILE__); + ut_d(trx->start_line = __LINE__); +#endif /* WITH_WSREP */ trx_start_low(trx); /* fall through */ case TRX_STATE_ACTIVE: diff --git a/storage/xtradb/dict/dict0dict.c b/storage/xtradb/dict/dict0dict.c index 29063f028f1..4c6875bca10 100644 --- a/storage/xtradb/dict/dict0dict.c +++ b/storage/xtradb/dict/dict0dict.c @@ -2586,7 +2586,26 @@ next_rec: return(NULL); } - +#ifdef WITH_WSREP +dict_index_t* +wsrep_dict_foreign_find_index( +/*====================*/ + dict_table_t* table, /*!< in: table */ + const char** columns,/*!< in: array of column names */ + ulint n_cols, /*!< in: number of columns */ + dict_index_t* types_idx, /*!< in: NULL or an index to whose types the + column types must match */ + ibool check_charsets, + /*!< in: whether to check charsets. + only has an effect if types_idx != NULL */ + ulint check_null) + /*!< in: nonzero if none of the columns must + be declared NOT NULL */ +{ + return dict_foreign_find_index( + table, columns, n_cols, types_idx, check_charsets, check_null); +} +#endif /* WITH_WSREP */ /**********************************************************************//** Find an index that is equivalent to the one passed in and is not marked for deletion. diff --git a/storage/xtradb/handler/ha_innodb.cc b/storage/xtradb/handler/ha_innodb.cc index 3573943dbc4..fdef9e104c5 100644 --- a/storage/xtradb/handler/ha_innodb.cc +++ b/storage/xtradb/handler/ha_innodb.cc @@ -99,6 +99,12 @@ extern "C" { #include "ha_prototypes.h" #include "ut0mem.h" #include "ibuf0ibuf.h" +#ifdef WITH_WSREP +#include "../storage/innobase/include/ut0byte.h" +#ifndef EXTRA_DEBUG + //#include "../storage/innobase/include/ut0byte.ic" +#endif /* EXTRA_DEBUG */ +#endif /* WITH_WSREP */ } #include "ha_innodb.h" @@ -116,6 +122,32 @@ extern ib_int64_t trx_sys_mysql_relay_log_pos; # define MYSQL_PLUGIN_IMPORT /* nothing */ # endif /* MYSQL_PLUGIN_IMPORT */ +#ifdef WITH_WSREP +#include <wsrep_mysqld.h> +#include <my_md5.h> +extern my_bool wsrep_certify_nonPK; +class binlog_trx_data; +extern handlerton *binlog_hton; + +extern MYSQL_PLUGIN_IMPORT MYSQL_BIN_LOG mysql_bin_log; +extern MYSQL_PLUGIN_IMPORT mysql_mutex_t LOCK_wsrep_rollback; +extern MYSQL_PLUGIN_IMPORT mysql_cond_t COND_wsrep_rollback; +extern MYSQL_PLUGIN_IMPORT wsrep_aborting_thd_t wsrep_aborting_thd; + +static inline wsrep_trx_handle_t* +wsrep_trx_handle(THD* thd, const trx_t* trx) { + return wsrep_trx_handle_for_id(wsrep_thd_trx_handle(thd), + (wsrep_trx_id_t)trx->id); +} + +extern bool wsrep_prepare_key_for_innodb(const uchar *cache_key, + size_t cache_key_len, + const uchar* row_id, + size_t row_id_len, + wsrep_key_part_t* key, + size_t* key_len); + +#endif /* WITH_WSREP */ /** to protect innobase_open_files */ static mysql_mutex_t innobase_share_mutex; static ulong commit_threads = 0; @@ -1086,6 +1118,15 @@ thd_to_trx( { return(*(trx_t**) thd_ha_data(thd, innodb_hton_ptr)); } +#ifdef WITH_WSREP +ulonglong +thd_to_trx_id( +/*=======*/ + THD* thd) /*!< in: MySQL thread */ +{ + return(thd_to_trx(thd)->id); +} +#endif my_bool ha_innobase::is_fake_change_enabled(THD* thd) @@ -1123,6 +1164,13 @@ innobase_release_temporary_latches( return(0); } +#ifdef WITH_WSREP +static int +wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, + my_bool signal); +static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid); +static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid); +#endif /********************************************************************//** Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth time calls srv_active_wake_master_thread. This function should be used @@ -1494,6 +1542,9 @@ int innobase_mysql_tmpfile(void) /*========================*/ { +#ifdef WITH_INNODB_DISALLOW_WRITES + os_event_wait(srv_allow_writes_event); +#endif /* WITH_INNODB_DISALLOW_WRITES */ int fd2 = -1; File fd; @@ -2616,6 +2667,11 @@ innobase_init( innobase_hton->flags=HTON_NO_FLAGS; innobase_hton->release_temporary_latches=innobase_release_temporary_latches; innobase_hton->alter_table_flags = innobase_alter_table_flags; +#ifdef WITH_WSREP + innobase_hton->wsrep_abort_transaction=wsrep_abort_transaction; + innobase_hton->wsrep_set_checkpoint=innobase_wsrep_set_checkpoint; + innobase_hton->wsrep_get_checkpoint=innobase_wsrep_get_checkpoint; +#endif /* WITH_WSREP */ innobase_hton->kill_query = innobase_kill_query; if (srv_file_per_table) @@ -3370,6 +3426,27 @@ innobase_commit_low( trx_commit_for_mysql(trx); } +#ifdef WITH_WSREP + THD* thd = (THD*)trx->mysql_thd; + const char* tmp = 0; + if (wsrep_on((void*)thd)) { +#ifdef WSREP_PROC_INFO + char info[64]; + info[sizeof(info) - 1] = '\0'; + snprintf(info, sizeof(info) - 1, + "innobase_commit_low():trx_commit_for_mysql(%lld)", + (long long) wsrep_thd_trx_seqno(thd)); + tmp = thd_proc_info(thd, info); + +#else + tmp = thd_proc_info(thd, "innobase_commit_low()"); +#endif /* WSREP_PROC_INFO */ + } +#endif /* WITH_WSREP */ + trx_commit_for_mysql(trx); +#ifdef WITH_WSREP + if (wsrep_on((void*)thd)) { thd_proc_info(thd, tmp); } +#endif /* WITH_WSREP */ } /*****************************************************************//** @@ -4131,7 +4208,11 @@ ha_innobase::max_supported_key_length() const therefore set to slightly less than 1 / 4 of page size which is 16 kB; but currently MySQL does not work with keys whose size is > MAX_KEY_LENGTH */ +#ifdef WITH_WSREP + return(3500); +#else return(3500); +#endif } /****************************************************************//** @@ -5232,7 +5313,96 @@ innobase_mysql_cmp( return(0); } +#ifdef WITH_WSREP +UNIV_INTERN +void +wsrep_innobase_mysql_sort( +/*===============*/ + /* out: str contains sort string */ + int mysql_type, /* in: MySQL type */ + uint charset_number, /* in: number of the charset */ + unsigned char* str, /* in: data field */ + unsigned int str_length) /* in: data field length, + not UNIV_SQL_NULL */ +{ + CHARSET_INFO* charset; + enum_field_types mysql_tp; + + DBUG_ASSERT(str_length != UNIV_SQL_NULL); + + mysql_tp = (enum_field_types) mysql_type; + + switch (mysql_tp) { + + case MYSQL_TYPE_BIT: + case MYSQL_TYPE_STRING: + case MYSQL_TYPE_VAR_STRING: + case MYSQL_TYPE_TINY_BLOB: + case MYSQL_TYPE_MEDIUM_BLOB: + case MYSQL_TYPE_BLOB: + case MYSQL_TYPE_LONG_BLOB: + case MYSQL_TYPE_VARCHAR: + { + uchar tmp_str[REC_VERSION_56_MAX_INDEX_COL_LEN]; + uint tmp_length = REC_VERSION_56_MAX_INDEX_COL_LEN; + + /* Use the charset number to pick the right charset struct for + the comparison. Since the MySQL function get_charset may be + slow before Bar removes the mutex operation there, we first + look at 2 common charsets directly. */ + + if (charset_number == default_charset_info->number) { + charset = default_charset_info; + } else if (charset_number == my_charset_latin1.number) { + charset = &my_charset_latin1; + } else { + charset = get_charset(charset_number, MYF(MY_WME)); + + if (charset == NULL) { + sql_print_error("InnoDB needs charset %lu for doing " + "a comparison, but MySQL cannot " + "find that charset.", + (ulong) charset_number); + ut_a(0); + } + } + + ut_a(str_length <= tmp_length); + memcpy(tmp_str, str, str_length); + tmp_length = charset->coll->strnxfrm(charset, str, str_length, + tmp_str, str_length); + DBUG_ASSERT(tmp_length == str_length); + + break; + } + case MYSQL_TYPE_DECIMAL : + case MYSQL_TYPE_TINY : + case MYSQL_TYPE_SHORT : + case MYSQL_TYPE_LONG : + case MYSQL_TYPE_FLOAT : + case MYSQL_TYPE_DOUBLE : + case MYSQL_TYPE_NULL : + case MYSQL_TYPE_TIMESTAMP : + case MYSQL_TYPE_LONGLONG : + case MYSQL_TYPE_INT24 : + case MYSQL_TYPE_DATE : + case MYSQL_TYPE_TIME : + case MYSQL_TYPE_DATETIME : + case MYSQL_TYPE_YEAR : + case MYSQL_TYPE_NEWDATE : + case MYSQL_TYPE_NEWDECIMAL : + case MYSQL_TYPE_ENUM : + case MYSQL_TYPE_SET : + case MYSQL_TYPE_GEOMETRY : + break; + default: + break; + } + + return; +} +#endif // WITH_WSREP /**************************************************************//** Converts a MySQL type to an InnoDB type. Note that this function returns the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1 @@ -5386,6 +5556,264 @@ innobase_read_from_2_little_endian( /*******************************************************************//** Stores a key value for a row to a buffer. @return key value length as stored in buff */ +#ifdef WITH_WSREP +UNIV_INTERN +uint +wsrep_store_key_val_for_row( +/*===============================*/ + TABLE* table, + uint keynr, /*!< in: key number */ + char* buff, /*!< in/out: buffer for the key value (in MySQL + format) */ + uint buff_len,/*!< in: buffer length */ + const uchar* record, + ibool* key_is_null)/*!< out: full key was null */ +{ + KEY* key_info = table->key_info + keynr; + KEY_PART_INFO* key_part = key_info->key_part; + KEY_PART_INFO* end = key_part + key_info->key_parts; + char* buff_start = buff; + enum_field_types mysql_type; + Field* field; + + DBUG_ENTER("store_key_val_for_row"); + + bzero(buff, buff_len); + *key_is_null = TRUE; + + for (; key_part != end; key_part++) { + uchar sorted[REC_VERSION_56_MAX_INDEX_COL_LEN] = {'\0'}; + ibool part_is_null = FALSE; + + if (key_part->null_bit) { + if (record[key_part->null_offset] & + key_part->null_bit) { + *buff = 1; + part_is_null = TRUE; + } else { + *buff = 0; + } + buff++; + } + if (!part_is_null) *key_is_null = FALSE; + + field = key_part->field; + mysql_type = field->type(); + + if (mysql_type == MYSQL_TYPE_VARCHAR) { + /* >= 5.0.3 true VARCHAR */ + ulint lenlen; + ulint len; + const byte* data; + ulint key_len; + ulint true_len; + CHARSET_INFO* cs; + int error=0; + + key_len = key_part->length; + + if (part_is_null) { + buff += key_len + 2; + + continue; + } + cs = field->charset(); + + lenlen = (ulint) + (((Field_varstring*)field)->length_bytes); + + data = row_mysql_read_true_varchar(&len, + (byte*) (record + + (ulint)get_field_offset(table, field)), + lenlen); + + true_len = len; + + /* For multi byte character sets we need to calculate + the true length of the key */ + + if (len > 0 && cs->mbmaxlen > 1) { + true_len = (ulint) cs->cset->well_formed_len(cs, + (const char *) data, + (const char *) data + len, + (uint) (key_len / + cs->mbmaxlen), + &error); + } + + /* In a column prefix index, we may need to truncate + the stored value: */ + + if (true_len > key_len) { + true_len = key_len; + } + + memcpy(sorted, data, true_len); + wsrep_innobase_mysql_sort( + mysql_type, cs->number, sorted, true_len); + + if (wsrep_protocol_version > 1) { + memcpy(buff, sorted, true_len); + /* Note that we always reserve the maximum possible + length of the true VARCHAR in the key value, though + only len first bytes after the 2 length bytes contain + actual data. The rest of the space was reset to zero + in the bzero() call above. */ + buff += true_len; + } else { + buff += key_len; + } + } else if (mysql_type == MYSQL_TYPE_TINY_BLOB + || mysql_type == MYSQL_TYPE_MEDIUM_BLOB + || mysql_type == MYSQL_TYPE_BLOB + || mysql_type == MYSQL_TYPE_LONG_BLOB + /* MYSQL_TYPE_GEOMETRY data is treated + as BLOB data in innodb. */ + || mysql_type == MYSQL_TYPE_GEOMETRY) { + + CHARSET_INFO* cs; + ulint key_len; + ulint true_len; + int error=0; + ulint blob_len; + const byte* blob_data; + + ut_a(key_part->key_part_flag & HA_PART_KEY_SEG); + + key_len = key_part->length; + + if (part_is_null) { + buff += key_len + 2; + + continue; + } + + cs = field->charset(); + + blob_data = row_mysql_read_blob_ref(&blob_len, + (byte*) (record + + (ulint)get_field_offset(table, field)), + (ulint) field->pack_length()); + + true_len = blob_len; + + ut_a(get_field_offset(table, field) + == key_part->offset); + + /* For multi byte character sets we need to calculate + the true length of the key */ + + if (blob_len > 0 && cs->mbmaxlen > 1) { + true_len = (ulint) cs->cset->well_formed_len(cs, + (const char *) blob_data, + (const char *) blob_data + + blob_len, + (uint) (key_len / + cs->mbmaxlen), + &error); + } + + /* All indexes on BLOB and TEXT are column prefix + indexes, and we may need to truncate the data to be + stored in the key value: */ + + if (true_len > key_len) { + true_len = key_len; + } + + memcpy(sorted, blob_data, true_len); + wsrep_innobase_mysql_sort( + mysql_type, cs->number, sorted, true_len); + + memcpy(buff, sorted, true_len); + + /* Note that we always reserve the maximum possible + length of the BLOB prefix in the key value. */ + if (wsrep_protocol_version > 1) { + buff += true_len; + } else { + buff += key_len; + } + } else { + /* Here we handle all other data types except the + true VARCHAR, BLOB and TEXT. Note that the column + value we store may be also in a column prefix + index. */ + + CHARSET_INFO* cs; + ulint true_len; + ulint key_len; + const uchar* src_start; + int error=0; + enum_field_types real_type; + + key_len = key_part->length; + + if (part_is_null) { + buff += key_len; + + continue; + } + + src_start = record + key_part->offset; + real_type = field->real_type(); + true_len = key_len; + + /* Character set for the field is defined only + to fields whose type is string and real field + type is not enum or set. For these fields check + if character set is multi byte. */ + + if (real_type != MYSQL_TYPE_ENUM + && real_type != MYSQL_TYPE_SET + && ( mysql_type == MYSQL_TYPE_VAR_STRING + || mysql_type == MYSQL_TYPE_STRING)) { + + cs = field->charset(); + + /* For multi byte character sets we need to + calculate the true length of the key */ + + if (key_len > 0 && cs->mbmaxlen > 1) { + + true_len = (ulint) + cs->cset->well_formed_len(cs, + (const char *)src_start, + (const char *)src_start + + key_len, + (uint) (key_len / + cs->mbmaxlen), + &error); + } + memcpy(sorted, src_start, true_len); + wsrep_innobase_mysql_sort( + mysql_type, cs->number, sorted, true_len); + memcpy(buff, sorted, true_len); + } else { + memcpy(buff, src_start, true_len); + } + buff += true_len; + + /* Pad the unused space with spaces. */ + +#ifdef REMOVED + if (true_len < key_len) { + ulint pad_len = key_len - true_len; + ut_a(!(pad_len % cs->mbminlen)); + + cs->cset->fill(cs, buff, pad_len, + 0x20 /* space */); + buff += pad_len; + } +#endif /* REMOVED */ + } + } + + ut_a(buff <= buff_start + buff_len); + + DBUG_RETURN((uint)(buff - buff_start)); +} +#endif /* WITH_WSREP */ UNIV_INTERN uint ha_innobase::store_key_val_for_row( @@ -6196,6 +6624,9 @@ ha_innobase::write_row( ulint error = 0; int error_result= 0; ibool auto_inc_used= FALSE; +#ifdef WITH_WSREP + ibool auto_inc_inserted= FALSE; /* if NULL was inserted */ +#endif ulint sql_command; trx_t* trx = thd_to_trx(user_thd); @@ -6225,8 +6656,17 @@ ha_innobase::write_row( if ((sql_command == SQLCOM_ALTER_TABLE || sql_command == SQLCOM_OPTIMIZE || sql_command == SQLCOM_CREATE_INDEX +#ifdef WITH_WSREP + || (wsrep_on(user_thd) && sql_command == SQLCOM_LOAD) +#endif /* WITH_WSREP */ || sql_command == SQLCOM_DROP_INDEX) && num_write_row >= 10000) { +#ifdef WITH_WSREP + if (wsrep_on(user_thd) && sql_command == SQLCOM_LOAD) { + WSREP_DEBUG("forced trx split for LOAD: %s", + wsrep_thd_query(user_thd)); + } +#endif /* WITH_WSREP */ /* ALTER TABLE is COMMITted at every 10000 copied rows. The IX table lock for the original table has to be re-issued. As this method will be called on a temporary table where the @@ -6298,7 +6738,9 @@ no_commit: /* Reset the error code before calling innobase_get_auto_increment(). */ prebuilt->autoinc_error = DB_SUCCESS; - +#ifdef WITH_WSREP + auto_inc_inserted= (table->next_number_field->val_int() == 0); +#endif if ((error = update_auto_increment())) { /* We don't want to mask autoinc overflow errors. */ @@ -6387,6 +6829,30 @@ no_commit: case SQLCOM_REPLACE_SELECT: goto set_max_autoinc; +#ifdef WITH_WSREP + /* workaround for LP bug #355000, retrying the insert */ + case SQLCOM_INSERT: + if (wsrep_on(current_thd) && + auto_inc_inserted && + wsrep_drupal_282555_workaround && + !thd_test_options(current_thd, + OPTION_NOT_AUTOCOMMIT | + OPTION_BEGIN)) { + WSREP_DEBUG( + "retrying insert: %s", + (*wsrep_thd_query(current_thd)) ? + wsrep_thd_query(current_thd) : + (char *)"void"); + error= DB_SUCCESS; + wsrep_thd_set_conflict_state( + current_thd, MUST_ABORT); + innodb_srv_conc_exit_innodb(prebuilt->trx); + /* jump straight to func exit over + * later wsrep hooks */ + goto func_exit; + } + break; +#endif default: break; } @@ -6435,6 +6901,20 @@ report_error: error_result = convert_error_code_to_mysql((int) error, prebuilt->table->flags, user_thd); +#ifdef WITH_WSREP + if (!error_result && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && + wsrep_on(user_thd) && !wsrep_consistency_check(user_thd) && + (sql_command != SQLCOM_LOAD || + thd_binlog_format(user_thd) == BINLOG_FORMAT_ROW)) { + + if (wsrep_append_keys(user_thd, false, record, NULL)) { + DBUG_PRINT("wsrep", ("row key failed")); + error_result = HA_ERR_INTERNAL_ERROR; + goto wsrep_error; + } + } +wsrep_error: +#endif func_exit: innobase_active_small(); @@ -6598,7 +7078,84 @@ calc_row_difference( return(0); } +#ifdef WITH_WSREP +static +int +wsrep_calc_row_hash( +/*================*/ + byte* digest, /*!< in/out: md5 sum */ + const uchar* row, /*!< in: row in MySQL format */ + TABLE* table, /*!< in: table in MySQL data + dictionary */ + row_prebuilt_t* prebuilt, /*!< in: InnoDB prebuilt struct */ + THD* thd) /*!< in: user thread */ +{ + Field* field; + enum_field_types field_mysql_type; + uint n_fields; + ulint len; + const byte* ptr; + ulint col_type; + uint i; + + my_MD5Context ctx; + my_MD5Init (&ctx); + + n_fields = table->s->fields; + for (i = 0; i < n_fields; i++) { + byte null_byte=0; + byte true_byte=1; + + field = table->field[i]; + + ptr = (const byte*) row + get_field_offset(table, field); + len = field->pack_length(); + + field_mysql_type = field->type(); + + col_type = prebuilt->table->cols[i].mtype; + + switch (col_type) { + + case DATA_BLOB: + ptr = row_mysql_read_blob_ref(&len, ptr, len); + + break; + + case DATA_VARCHAR: + case DATA_BINARY: + case DATA_VARMYSQL: + if (field_mysql_type == MYSQL_TYPE_VARCHAR) { + /* This is a >= 5.0.3 type true VARCHAR where + the real payload data length is stored in + 1 or 2 bytes */ + + ptr = row_mysql_read_true_varchar( + &len, ptr, + (ulint) + (((Field_varstring*)field)->length_bytes)); + + } + + break; + default: + ; + } + + if (field->null_ptr && + field_in_record_is_null(table, field, (char*) row)) { + my_MD5Update (&ctx, &null_byte, 1); + } else { + my_MD5Update (&ctx, &true_byte, 1); + my_MD5Update (&ctx, ptr, len); + } + } + my_MD5Final (digest, &ctx); + + return(0); +} +#endif /* WITH_WSREP */ /**********************************************************************//** Updates a row given as a parameter to a new value. Note that we are given whole rows, not just the fields which are updated: this incurs some @@ -6733,6 +7290,20 @@ ha_innobase::update_row( DBUG_RETURN(HA_ERR_CRASHED); } +#ifdef WITH_WSREP + if (!error && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && + wsrep_on(user_thd)) { + + DBUG_PRINT("wsrep", ("update row key")); + + if (wsrep_append_keys(user_thd, false, old_row, new_row)) { + DBUG_PRINT("wsrep", ("row key failed")); + error = HA_ERR_INTERNAL_ERROR; + goto wsrep_error; + } + } +wsrep_error: +#endif DBUG_RETURN(error); } @@ -6788,6 +7359,18 @@ ha_innobase::delete_row( DBUG_RETURN(HA_ERR_CRASHED); } +#ifdef WITH_WSREP + if (!error && wsrep_thd_exec_mode(user_thd) == LOCAL_STATE && + wsrep_on(user_thd)) { + + if (wsrep_append_keys(user_thd, false, record, NULL)) { + DBUG_PRINT("wsrep", ("delete fail")); + error = HA_ERR_INTERNAL_ERROR; + goto wsrep_error; + } + } +wsrep_error: +#endif DBUG_RETURN(error); } @@ -7594,7 +8177,377 @@ ha_innobase::rnd_pos( DBUG_RETURN(error); } +#ifdef WITH_WSREP +extern "C" { +dict_index_t* +wsrep_dict_foreign_find_index( + dict_table_t* table, + const char** columns, + ulint n_cols, + dict_index_t* types_idx, + ibool check_charsets, + ulint check_null); + +ulint +wsrep_append_foreign_key( +/*===========================*/ + trx_t* trx, /*!< in: trx */ + dict_foreign_t* foreign, /*!< in: foreign key constraint */ + const rec_t* rec, /*!<in: clustered index record */ + dict_index_t* index, /*!<in: clustered index */ + ibool referenced, /*!<in: is check for referenced table */ + ibool shared) /*!<in: is shared access */ +{ + ut_a(trx); + THD* thd = (THD*)trx->mysql_thd; + ulint rcode = DB_SUCCESS; + char cache_key[513] = {'\0'}; + int cache_key_len; + + if (!wsrep_on(trx->mysql_thd) || + wsrep_thd_exec_mode(thd) != LOCAL_STATE) + return DB_SUCCESS; + + if (!thd || !foreign || + (!foreign->referenced_table && !foreign->foreign_table)) + { + WSREP_INFO("FK: %s missing in: %s", + (!thd) ? "thread" : + ((!foreign) ? "constraint" : + ((!foreign->referenced_table) ? + "referenced table" : "foreign table")), + (thd && wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + return DB_ERROR; + } + + if ( !((referenced) ? + foreign->referenced_table : foreign->foreign_table)) + { + WSREP_DEBUG("pulling %s table into cache", + (referenced) ? "referenced" : "foreign"); + mutex_enter(&(dict_sys->mutex)); + if (referenced) + { + foreign->referenced_table = + dict_table_get_low( + foreign->referenced_table_name_lookup); + if (foreign->referenced_table) + { + foreign->referenced_index = + wsrep_dict_foreign_find_index( + foreign->referenced_table, + foreign->referenced_col_names, + foreign->n_fields, + foreign->foreign_index, + TRUE, FALSE); + } + } + else + { + foreign->foreign_table = + dict_table_get_low( + foreign->foreign_table_name_lookup); + if (foreign->foreign_table) + { + foreign->foreign_index = + wsrep_dict_foreign_find_index( + foreign->foreign_table, + foreign->foreign_col_names, + foreign->n_fields, + foreign->referenced_index, + TRUE, FALSE); + } + } + mutex_exit(&(dict_sys->mutex)); + } + + if ( !((referenced) ? + foreign->referenced_table : foreign->foreign_table)) + { + WSREP_WARN("FK: %s missing in query: %s", + (!foreign->referenced_table) ? + "referenced table" : "foreign table", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + return DB_ERROR; + } + byte key[WSREP_MAX_SUPPORTED_KEY_LENGTH+1]; + ulint len = WSREP_MAX_SUPPORTED_KEY_LENGTH; + + dict_index_t *idx_target = (referenced) ? + foreign->referenced_index : index; + dict_index_t *idx = (referenced) ? + UT_LIST_GET_FIRST(foreign->referenced_table->indexes) : + UT_LIST_GET_FIRST(foreign->foreign_table->indexes); + int i = 0; + while (idx != NULL && idx != idx_target) { + idx = UT_LIST_GET_NEXT(indexes, idx); + i++; + } + ut_a(idx); + key[0] = (char)i; + + rcode = wsrep_rec_get_foreign_key( + &key[1], &len, rec, index, idx, + wsrep_protocol_version > 1); + if (rcode != DB_SUCCESS) { + WSREP_ERROR( + "FK key set failed: %lu (%lu %lu), index: %s %s, %s", + rcode, referenced, shared, + (index && index->name) ? index->name : + "void index", + (index && index->table_name) ? index->table_name : + "void table", + wsrep_thd_query(thd)); + return rcode; + } + strncpy(cache_key, + (wsrep_protocol_version > 1) ? + ((referenced) ? + foreign->referenced_table->name : + foreign->foreign_table->name) : + foreign->foreign_table->name, sizeof(cache_key) - 1); + cache_key_len = strlen(cache_key); +#ifdef WSREP_DEBUG_PRINT + ulint j; + fprintf(stderr, "FK parent key, table: %s %s len: %lu ", + cache_key, (shared) ? "shared" : "exclusive", len+1); + for (j=0; j<len+1; j++) { + fprintf(stderr, " %hhX, ", key[j]); + } + fprintf(stderr, "\n"); +#endif + char *p = strchr(cache_key, '/'); + if (p) { + *p = '\0'; + } else { + WSREP_WARN("unexpected foreign key table %s %s", + foreign->referenced_table->name, + foreign->foreign_table->name); + } + + wsrep_key_part_t wkey_part[3]; + wsrep_key_t wkey = {wkey_part, 3}; + if (!wsrep_prepare_key_for_innodb( + (const uchar*)cache_key, + cache_key_len + 1, + (const uchar*)key, len+1, + wkey_part, + &wkey.key_parts_len)) { + WSREP_WARN("key prepare failed for cascaded FK: %s", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + return DB_ERROR; + } + rcode = (int)wsrep->append_key( + wsrep, + wsrep_trx_handle(thd, trx), + &wkey, + 1, + shared); + if (rcode) { + DBUG_PRINT("wsrep", ("row key failed: %lu", rcode)); + WSREP_ERROR("Appending cascaded fk row key failed: %s, %lu", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void", rcode); + return DB_ERROR; + } + + return DB_SUCCESS; +} +} + +static int +wsrep_append_key( +/*==================*/ + THD *thd, + trx_t *trx, + TABLE_SHARE *table_share, + TABLE *table, + const char* key, + uint16_t key_len, + bool shared +) +{ + DBUG_ENTER("wsrep_append_key"); +#ifdef WSREP_DEBUG_PRINT + fprintf(stderr, "%s conn %ld, trx %llu, keylen %d, table %s ", + (shared) ? "Shared" : "Exclusive", + wsrep_thd_thread_id(thd), trx->id, key_len, + table_share->table_name.str); + for (int i=0; i<key_len; i++) { + fprintf(stderr, "%hhX, ", key[i]); + } + fprintf(stderr, "\n"); +#endif + wsrep_key_part_t wkey_part[3]; + wsrep_key_t wkey = {wkey_part, 3}; + if (!wsrep_prepare_key_for_innodb( + (const uchar*)table_share->table_cache_key.str, + table_share->table_cache_key.length, + (const uchar*)key, key_len, + wkey_part, + &wkey.key_parts_len)) { + WSREP_WARN("key prepare failed for: %s", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + DBUG_RETURN(HA_ERR_INTERNAL_ERROR); + } + + int rcode = (int)wsrep->append_key( + wsrep, + wsrep_trx_handle(thd, trx), + &wkey, + 1, + shared); + if (rcode) { + DBUG_PRINT("wsrep", ("row key failed: %d", rcode)); + WSREP_WARN("Appending row key failed: %s, %d", + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void", rcode); + DBUG_RETURN(rcode); + } + DBUG_RETURN(0); +} + +ibool +wsrep_is_cascding_foreign_key_parent( + dict_table_t* table, /*!< in: InnoDB table */ + dict_index_t* index /*!< in: InnoDB index */ +) { + // return referenced_by_foreign_key(); + dict_foreign_t* fk = dict_table_get_referenced_constraint(table, index); + if (fk && + (fk->type & DICT_FOREIGN_ON_UPDATE_CASCADE || + fk->type & DICT_FOREIGN_ON_UPDATE_SET_NULL) + ) { + return TRUE; + } + return FALSE; +} + +int +ha_innobase::wsrep_append_keys( +/*==================*/ + THD *thd, + bool shared, + const uchar* record0, /* in: row in MySQL format */ + const uchar* record1) /* in: row in MySQL format */ +{ + DBUG_ENTER("wsrep_append_keys"); + + bool key_appended = false; + trx_t *trx = thd_to_trx(thd); + + if (table_share && table_share->tmp_table != NO_TMP_TABLE) { + WSREP_DEBUG("skipping tmp table DML: THD: %lu tmp: %d SQL: %s", + wsrep_thd_thread_id(thd), + table_share->tmp_table, + (wsrep_thd_query(thd)) ? + wsrep_thd_query(thd) : "void"); + DBUG_RETURN(0); + } + if (wsrep_protocol_version == 0) { + uint len; + char keyval[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; + char *key = &keyval[0]; + KEY *key_info = table->key_info; + ibool is_null; + + len = wsrep_store_key_val_for_row( + table, 0, key, key_info->key_length, record0, &is_null); + + if (!is_null) { + int rcode = wsrep_append_key( + thd, trx, table_share, table, keyval, + len, shared); + if (rcode) DBUG_RETURN(rcode); + } + else + { + WSREP_DEBUG("NULL key skipped (proto 0): %s", + wsrep_thd_query(thd)); + } + } else { + ut_a(table->s->keys <= 256); + uint i; + for (i=0; i<table->s->keys; ++i) { + uint len; + char keyval0[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; + char keyval1[WSREP_MAX_SUPPORTED_KEY_LENGTH+1] = {'\0'}; + char *key0 = &keyval0[1]; + char *key1 = &keyval1[1]; + KEY *key_info = table->key_info + i; + ibool is_null; + + keyval0[0] = (char)i; + keyval1[0] = (char)i; + + if (key_info->flags & HA_NOSAME || + referenced_by_foreign_key()) { + if (key_info->flags & HA_NOSAME || shared) + key_appended = true; + + len = wsrep_store_key_val_for_row( + table, i, key0, key_info->key_length, + record0, &is_null); + if (!is_null) { + int rcode = wsrep_append_key( + thd, trx, table_share, table, + keyval0, len+1, shared); + if (rcode) DBUG_RETURN(rcode); + } + else + { + WSREP_DEBUG("NULL key skipped: %s", + wsrep_thd_query(thd)); + } + if (record1) { + len = wsrep_store_key_val_for_row( + table, i, key1, key_info->key_length, + record1, &is_null); + if (!is_null && memcmp(key0, key1, len)) { + int rcode = wsrep_append_key( + thd, trx, table_share, + table, + keyval1, len+1, shared); + if (rcode) DBUG_RETURN(rcode); + } + } + } + } + } + + /* if no PK, calculate hash of full row, to be the key value */ + if (!key_appended && wsrep_certify_nonPK) { + uchar digest[16]; + int rcode; + + wsrep_calc_row_hash(digest, record0, table, prebuilt, thd); + if ((rcode = wsrep_append_key(thd, trx, table_share, table, + (const char*) digest, 16, + shared))) { + DBUG_RETURN(rcode); + } + + if (record1) { + wsrep_calc_row_hash( + digest, record1, table, prebuilt, thd); + if ((rcode = wsrep_append_key(thd, trx, table_share, + table, + (const char*) digest, + 16, shared))) { + DBUG_RETURN(rcode); + } + } + DBUG_RETURN(0); + } + + DBUG_RETURN(0); +} +#endif /*********************************************************************//** Stores a reference to the current row to 'ref' field of the handle. Note that in the case where we have generated the clustered index for the @@ -10563,11 +11516,18 @@ ha_innobase::external_lock( /* used by test case */ DBUG_EXECUTE_IF("no_innodb_binlog_errors", skip = 1;); if (!skip) { +#ifdef WITH_WSREP + if (!wsrep_on(thd) || wsrep_thd_exec_mode(thd) == LOCAL_STATE) + { +#endif /* WITH_WSREP */ my_error(ER_BINLOG_STMT_MODE_AND_ROW_ENGINE, MYF(0), " InnoDB is limited to row-logging when " "transaction isolation level is " "READ COMMITTED or READ UNCOMMITTED."); DBUG_RETURN(HA_ERR_LOGGING_IMPOSSIBLE); +#ifdef WITH_WSREP + } +#endif /* WITH_WSREP */ } } @@ -11824,6 +12784,9 @@ innobase_xa_prepare( to the session variable take effect only in the next transaction */ if (!trx->support_xa) { +#ifdef WITH_WSREP + thd_get_xid(thd, (MYSQL_XID*) &trx->xid); +#endif // WITH_WSREP return(0); } @@ -12735,6 +13698,260 @@ static SHOW_VAR innodb_status_variables_export[]= { static struct st_mysql_storage_engine innobase_storage_engine= { MYSQL_HANDLERTON_INTERFACE_VERSION }; +#ifdef WITH_WSREP +void +wsrep_abort_slave_trx(wsrep_seqno_t bf_seqno, wsrep_seqno_t victim_seqno) +{ + WSREP_ERROR("Trx %lld tries to abort slave trx %lld. This could be " + "caused by:\n\t" + "1) unsupported configuration options combination, please check documentation.\n\t" + "2) a bug in the code.\n\t" + "3) a database corruption.\n Node consistency compromized, " + "need to abort. Restart the node to resync with cluster.", + (long long)bf_seqno, (long long)victim_seqno); + abort(); +} +int +wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx, ibool signal) +{ + DBUG_ENTER("wsrep_innobase_kill_one_trx"); + THD *thd = (THD *) victim_trx->mysql_thd; + THD *bf_thd = (bf_trx) ? (THD *)bf_trx->mysql_thd : NULL; + int64_t bf_seqno = (bf_thd) ? wsrep_thd_trx_seqno(bf_thd) : 0; + + if (!thd) { + DBUG_PRINT("wsrep", ("no thd for conflicting lock")); + WSREP_WARN("no THD for trx: %llu", victim_trx->id); + DBUG_RETURN(1); + } + + WSREP_DEBUG("BF kill (%lu, seqno: %lld), victim: (%lu) trx: %llu", + signal, (long long)bf_seqno, + wsrep_thd_thread_id(thd), + victim_trx->id); + + WSREP_DEBUG("Aborting query: %s", + (thd && wsrep_thd_query(thd)) ? wsrep_thd_query(thd) : "void"); + + wsrep_thd_LOCK(thd); + + if (wsrep_thd_query_state(thd) == QUERY_EXITING) { + WSREP_DEBUG("kill trx EXITING for %llu", victim_trx->id); + wsrep_thd_UNLOCK(thd); + DBUG_RETURN(0); + } + if(wsrep_thd_exec_mode(thd) != LOCAL_STATE) { + WSREP_DEBUG("withdraw for BF trx: %llu, state: %d", + victim_trx->id, + wsrep_thd_conflict_state(thd)); + } + + switch (wsrep_thd_conflict_state(thd)) { + case NO_CONFLICT: + wsrep_thd_set_conflict_state(thd, MUST_ABORT); + break; + case MUST_ABORT: + WSREP_DEBUG("victim %llu in MUST ABORT state", + victim_trx->id); + wsrep_thd_UNLOCK(thd); + wsrep_thd_awake(bf_thd, thd, signal); + DBUG_RETURN(0); + break; + case ABORTED: + case ABORTING: // fall through + default: + WSREP_DEBUG("victim %llu in state %d", + victim_trx->id, wsrep_thd_conflict_state(thd)); + wsrep_thd_UNLOCK(thd); + DBUG_RETURN(0); + break; + } + + switch (wsrep_thd_query_state(thd)) { + case QUERY_COMMITTING: + enum wsrep_status rcode; + + WSREP_DEBUG("kill query for: %ld", + wsrep_thd_thread_id(thd)); + wsrep_thd_awake(bf_thd, thd, signal); + WSREP_DEBUG("kill trx QUERY_COMMITTING for %llu", + victim_trx->id); + + if (wsrep_thd_exec_mode(thd) == REPL_RECV) { + wsrep_abort_slave_trx(bf_seqno, + wsrep_thd_trx_seqno(thd)); + } else { + rcode = wsrep->abort_pre_commit( + wsrep, bf_seqno, + (wsrep_trx_id_t)victim_trx->id + ); + + switch (rcode) { + case WSREP_WARNING: + WSREP_DEBUG("cancel commit warning: %llu", + victim_trx->id); + wsrep_thd_UNLOCK(thd); + DBUG_RETURN(1); + break; + case WSREP_OK: + break; + default: + WSREP_ERROR( + "cancel commit bad exit: %d %llu", + rcode, + victim_trx->id); + /* unable to interrupt, must abort */ + /* note: kill_mysql() will block, if we cannot. + * kill the lock holder first. + */ + abort(); + break; + } + } + break; + case QUERY_EXEC: + /* it is possible that victim trx is itself waiting for some + * other lock. We need to cancel this waiting + */ + WSREP_DEBUG("kill trx QUERY_EXEC for %llu", victim_trx->id); + + victim_trx->was_chosen_as_deadlock_victim= TRUE; + if (victim_trx->wait_lock) { + WSREP_DEBUG("victim has wait flag: %ld", + wsrep_thd_thread_id(thd)); + lock_t* wait_lock = victim_trx->wait_lock; + if (wait_lock) { + WSREP_DEBUG("canceling wait lock"); + victim_trx->was_chosen_as_deadlock_victim= TRUE; + lock_cancel_waiting_and_release(wait_lock); + } + + wsrep_thd_awake(bf_thd, thd, signal); + } else { + /* abort currently executing query */ + DBUG_PRINT("wsrep",("sending KILL_QUERY to: %ld", + wsrep_thd_thread_id(thd))); + WSREP_DEBUG("kill query for: %ld", + wsrep_thd_thread_id(thd)); + wsrep_thd_awake(bf_thd, thd, signal); + + /* for BF thd, we need to prevent him from committing */ + if (wsrep_thd_exec_mode(thd) == REPL_RECV) { + wsrep_abort_slave_trx(bf_seqno, + wsrep_thd_trx_seqno(thd)); + } + } + break; + case QUERY_IDLE: + { + bool skip_abort= false; + wsrep_aborting_thd_t abortees; + + WSREP_DEBUG("kill IDLE for %llu", victim_trx->id); + + if (wsrep_thd_exec_mode(thd) == REPL_RECV) { + WSREP_DEBUG("kill BF IDLE, seqno: %lld", + (long long)wsrep_thd_trx_seqno(thd)); + wsrep_thd_UNLOCK(thd); + wsrep_abort_slave_trx(bf_seqno, + wsrep_thd_trx_seqno(thd)); + DBUG_RETURN(0); + } + /* This will lock thd from proceeding after net_read() */ + wsrep_thd_set_conflict_state(thd, ABORTING); + + mysql_mutex_lock(&LOCK_wsrep_rollback); + + abortees = wsrep_aborting_thd; + while (abortees && !skip_abort) { + /* check if we have a kill message for this already */ + if (abortees->aborting_thd == thd) { + skip_abort = true; + WSREP_WARN("duplicate thd aborter %lu", + wsrep_thd_thread_id(thd)); + } + abortees = abortees->next; + } + if (!skip_abort) { + wsrep_aborting_thd_t aborting = (wsrep_aborting_thd_t) + my_malloc(sizeof(struct wsrep_aborting_thd), + MYF(0)); + aborting->aborting_thd = thd; + aborting->next = wsrep_aborting_thd; + wsrep_aborting_thd = aborting; + DBUG_PRINT("wsrep",("enqueuing trx abort for %lu", + wsrep_thd_thread_id(thd))); + WSREP_DEBUG("enqueuing trx abort for (%lu)", + wsrep_thd_thread_id(thd)); + } + + DBUG_PRINT("wsrep",("signalling wsrep rollbacker")); + WSREP_DEBUG("signaling aborter"); + mysql_cond_signal(&COND_wsrep_rollback); + mysql_mutex_unlock(&LOCK_wsrep_rollback); + + break; + } + default: + WSREP_WARN("bad wsrep query state: %d", + wsrep_thd_query_state(thd)); + break; + } + wsrep_thd_UNLOCK(thd); + + DBUG_RETURN(0); +} +static int +wsrep_abort_transaction(handlerton* hton, THD *bf_thd, THD *victim_thd, + my_bool signal) +{ + DBUG_ENTER("wsrep_innobase_abort_thd"); + trx_t* victim_trx = thd_to_trx(victim_thd); + trx_t* bf_trx = (bf_thd) ? thd_to_trx(bf_thd) : NULL; + WSREP_DEBUG("abort transaction: BF: %s victim: %s", + wsrep_thd_query(bf_thd), + wsrep_thd_query(victim_thd)); + + if (victim_trx) + { + mutex_enter(&kernel_mutex); + int rcode = wsrep_innobase_kill_one_trx(bf_trx, victim_trx, + signal); + mutex_exit(&kernel_mutex); + wsrep_srv_conc_cancel_wait(victim_trx); + DBUG_RETURN(rcode); + } else { + WSREP_DEBUG("victim does not have transaction"); + wsrep_thd_LOCK(victim_thd); + wsrep_thd_set_conflict_state(victim_thd, MUST_ABORT); + wsrep_thd_UNLOCK(victim_thd); + wsrep_thd_awake(bf_thd, victim_thd, signal); + } + DBUG_RETURN(-1); +} + +static int innobase_wsrep_set_checkpoint(handlerton* hton, const XID* xid) +{ + DBUG_ASSERT(hton == innodb_hton_ptr); + if (wsrep_is_wsrep_xid(xid)) { + mtr_t mtr; + mtr_start(&mtr); + trx_sys_update_wsrep_checkpoint(xid, &mtr); + mtr_commit(&mtr); + return 0; + } else { + return 1; + } +} + +static int innobase_wsrep_get_checkpoint(handlerton* hton, XID* xid) +{ + DBUG_ASSERT(hton == innodb_hton_ptr); + trx_sys_read_wsrep_checkpoint(xid); + return 0; +} + +#endif /* WITH_WSREP */ /* plugin options */ static MYSQL_SYSVAR_BOOL(checksums, innobase_use_checksums, PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, @@ -13213,6 +14430,40 @@ static MYSQL_SYSVAR_UINT(change_buffering_debug, ibuf_debug, NULL, NULL, 0, 0, 2, 0); #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ +#ifdef WITH_INNODB_DISALLOW_WRITES +/******************************************************* + * innobase_disallow_writes variable definition * + *******************************************************/ + +/* Must always init to FALSE. */ +static my_bool innobase_disallow_writes = FALSE; + +/************************************************************************** +An "update" method for innobase_disallow_writes variable. */ +static +void +innobase_disallow_writes_update( +/*============================*/ + THD* thd, /* in: thread handle */ + st_mysql_sys_var* var, /* in: pointer to system + variable */ + void* var_ptr, /* out: pointer to dynamic + variable */ + const void* save) /* in: temporary storage */ +{ + *(my_bool*)var_ptr = *(my_bool*)save; + ut_a(srv_allow_writes_event); + if (*(my_bool*)var_ptr) + os_event_reset(srv_allow_writes_event); + else + os_event_set(srv_allow_writes_event); +} + +static MYSQL_SYSVAR_BOOL(disallow_writes, innobase_disallow_writes, + PLUGIN_VAR_NOCMDOPT, + "Tell InnoDB to stop any writes to disk", + NULL, innobase_disallow_writes_update, FALSE); +#endif /* WITH_INNODB_DISALLOW_WRITES */ static MYSQL_SYSVAR_BOOL(random_read_ahead, srv_random_read_ahead, PLUGIN_VAR_NOCMDARG, "Whether to use read ahead for random access within an extent.", @@ -13523,6 +14774,9 @@ static struct st_mysql_sys_var* innobase_system_variables[]= { #if defined UNIV_DEBUG || defined UNIV_IBUF_DEBUG MYSQL_SYSVAR(change_buffering_debug), #endif /* UNIV_DEBUG || UNIV_IBUF_DEBUG */ +#ifdef WITH_INNODB_DISALLOW_WRITES + MYSQL_SYSVAR(disallow_writes), +#endif /* WITH_INNODB_DISALLOW_WRITES */ MYSQL_SYSVAR(random_read_ahead), MYSQL_SYSVAR(read_ahead_threshold), MYSQL_SYSVAR(io_capacity), diff --git a/storage/xtradb/handler/ha_innodb.h b/storage/xtradb/handler/ha_innodb.h index 439be10fddb..e9eb4fcbebc 100644 --- a/storage/xtradb/handler/ha_innodb.h +++ b/storage/xtradb/handler/ha_innodb.h @@ -114,6 +114,10 @@ class ha_innobase: public handler dict_index_t* innobase_get_index(uint keynr); int info_low(uint flag, bool called_from_analyze); +#ifdef WITH_WSREP + int wsrep_append_keys(THD *thd, bool shared, + const uchar* record0, const uchar* record1); +#endif /* Init values for the class: */ public: ha_innobase(handlerton *hton, TABLE_SHARE *table_arg); @@ -370,6 +374,37 @@ bool thd_sqlcom_can_generate_row_events(const MYSQL_THD thd); */ extern void mysql_bin_log_commit_pos(THD *thd, ulonglong *out_pos, const char **out_file); +#ifdef WITH_WSREP +#include <wsrep_mysqld.h> +//extern "C" int wsrep_trx_order_before(void *thd1, void *thd2); + +extern "C" bool wsrep_thd_is_wsrep_on(THD *thd); + +extern "C" enum wsrep_exec_mode wsrep_thd_exec_mode(THD *thd); +extern "C" enum wsrep_conflict_state wsrep_thd_conflict_state(THD *thd); +extern "C" enum wsrep_query_state wsrep_thd_query_state(THD *thd); +extern "C" wsrep_trx_handle_t* wsrep_thd_trx_handle(THD *thd); + +extern "C" void wsrep_thd_set_exec_mode(THD *thd, enum wsrep_exec_mode mode); +extern "C" void wsrep_thd_set_query_state( + THD *thd, enum wsrep_query_state state); +extern "C" void wsrep_thd_set_conflict_state( + THD *thd, enum wsrep_conflict_state state); + +extern "C" void wsrep_thd_set_trx_to_replay(THD *thd, uint64 trx_id); + +extern "C"void wsrep_thd_LOCK(THD *thd); +extern "C"void wsrep_thd_UNLOCK(THD *thd); +extern "C" uint32 wsrep_thd_wsrep_rand(THD *thd); +extern "C" time_t wsrep_thd_query_start(THD *thd); +extern "C" my_thread_id wsrep_thd_thread_id(THD *thd); +extern "C" int64_t wsrep_thd_trx_seqno(THD *thd); +extern "C" query_id_t wsrep_thd_query_id(THD *thd); +extern "C" char * wsrep_thd_query(THD *thd); +extern "C" query_id_t wsrep_thd_wsrep_last_query_id(THD *thd); +extern "C" void wsrep_thd_set_wsrep_last_query_id(THD *thd, query_id_t id); +extern "C" void wsrep_thd_awake(THD* bf_thd, THD *thd, my_bool signal); +#endif typedef struct trx_struct trx_t; /********************************************************************//** @file handler/ha_innodb.h @@ -410,3 +445,6 @@ innobase_index_name_is_reserved( ulint num_of_keys); /*!< in: Number of indexes to be created. */ +#ifdef WITH_WSREP +extern "C" int wsrep_trx_is_aborting(void *thd_ptr); +#endif diff --git a/storage/xtradb/handler/handler0alter.cc b/storage/xtradb/handler/handler0alter.cc index 9886e8f6bd9..dcb41469f41 100644 --- a/storage/xtradb/handler/handler0alter.cc +++ b/storage/xtradb/handler/handler0alter.cc @@ -37,6 +37,10 @@ extern "C" { #include "handler0alter.h" } +#ifdef WITH_WSREP +//#include "wsrep_api.h" +#include <sql_acl.h> // PROCESS_ACL +#endif #include "ha_innodb.h" /*************************************************************//** diff --git a/storage/xtradb/include/dict0mem.h b/storage/xtradb/include/dict0mem.h index 630942ae2ac..4ba09caae7f 100644 --- a/storage/xtradb/include/dict0mem.h +++ b/storage/xtradb/include/dict0mem.h @@ -343,6 +343,9 @@ barracuda format, the length could be REC_VERSION_56_MAX_INDEX_COL_LEN /** Defines the maximum fixed length column size */ #define DICT_MAX_FIXED_COL_LEN DICT_ANTELOPE_MAX_INDEX_COL_LEN +#ifdef WITH_WSREP +#define WSREP_MAX_SUPPORTED_KEY_LENGTH 3500 +#endif /* WITH_WSREP */ /** Data structure for a field in an index */ struct dict_field_struct{ diff --git a/storage/xtradb/include/ha_prototypes.h b/storage/xtradb/include/ha_prototypes.h index c2209c89029..4572658350b 100644 --- a/storage/xtradb/include/ha_prototypes.h +++ b/storage/xtradb/include/ha_prototypes.h @@ -311,6 +311,19 @@ thd_flush_log_at_trx_commit( /*================================*/ void* thd); +#ifdef WITH_WSREP +UNIV_INTERN +int +wsrep_innobase_kill_one_trx(trx_t *bf_trx, trx_t *victim_trx, ibool signal); +int wsrep_thd_is_brute_force(void *thd_ptr); +int wsrep_trx_order_before(void *thd1, void *thd2); +void wsrep_innobase_mysql_sort(int mysql_type, uint charset_number, + unsigned char* str, unsigned int str_length); +//UNIV_INTERN +int +wsrep_on(void *thd_ptr); +int wsrep_is_wsrep_xid(const void*); +#endif /* WITH_WSREP */ /**********************************************************************//** Get the current setting of the lower_case_table_names global parameter from mysqld.cc. We do a dirty read because for one there is no synchronization diff --git a/storage/xtradb/include/lock0lock.h b/storage/xtradb/include/lock0lock.h index 2b659ab417e..67a4cc2eb68 100644 --- a/storage/xtradb/include/lock0lock.h +++ b/storage/xtradb/include/lock0lock.h @@ -800,9 +800,7 @@ lock_rec_get_page_no( record */ #define LOCK_CONV_BY_OTHER 4096 /*!< this bit is set when the lock is created by other transaction */ -#if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_CONV_BY_OTHER)&LOCK_MODE_MASK -# error -#endif +#define WSREP_BF 8192 #if (LOCK_WAIT|LOCK_GAP|LOCK_REC_NOT_GAP|LOCK_INSERT_INTENTION|LOCK_CONV_BY_OTHER)&LOCK_TYPE_MASK # error #endif diff --git a/storage/xtradb/include/rem0rec.h b/storage/xtradb/include/rem0rec.h index 98bf889b996..5687f51d985 100644 --- a/storage/xtradb/include/rem0rec.h +++ b/storage/xtradb/include/rem0rec.h @@ -836,6 +836,15 @@ are given in one byte (resp. two byte) format. */ two upmost bits in a two byte offset for special purposes */ #define REC_MAX_DATA_SIZE (16 * 1024) +#ifdef WITH_WSREP +int wsrep_rec_get_foreign_key( + byte *buf, /* out: extracted key */ + ulint *buf_len, /* in/out: length of buf */ + const rec_t* rec, /* in: physical record */ + dict_index_t* index_for, /* in: index for foreign table */ + dict_index_t* index_ref, /* in: index for referenced table */ + ibool new_protocol); /* in: protocol > 1 */ +#endif /* WITH_WSREP */ #ifndef UNIV_NONINL #include "rem0rec.ic" #endif diff --git a/storage/xtradb/include/srv0srv.h b/storage/xtradb/include/srv0srv.h index 586c1e73879..17b32dff3be 100644 --- a/storage/xtradb/include/srv0srv.h +++ b/storage/xtradb/include/srv0srv.h @@ -166,6 +166,10 @@ extern ulint srv_log_buffer_size; extern char srv_use_global_flush_log_at_trx_commit; extern char srv_adaptive_flushing; +#ifdef WITH_INNODB_DISALLOW_WRITES +/* When this event is reset we do not allow any file writes to take place. */ +extern os_event_t srv_allow_writes_event; +#endif /* WITH_INNODB_DISALLOW_WRITES */ /* If this flag is TRUE, then we will load the indexes' (and tables') metadata even if they are marked as "corrupted". Mostly it is for DBA to process corrupted index and table */ @@ -643,6 +647,14 @@ srv_conc_enter_innodb( /*==================*/ trx_t* trx); /*!< in: transaction object associated with the thread */ +#ifdef WITH_WSREP +UNIV_INTERN +void +wsrep_srv_conc_cancel_wait( +/*==================*/ + trx_t* trx); /*!< in: transaction object associated with the + thread */ +#endif /* WITH_WSREP */ /*********************************************************************//** This lets a thread enter InnoDB regardless of the number of threads inside InnoDB. This must be called when a thread ends a lock wait. */ diff --git a/storage/xtradb/include/trx0sys.h b/storage/xtradb/include/trx0sys.h index cba21ae97a9..7ae3ba74478 100644 --- a/storage/xtradb/include/trx0sys.h +++ b/storage/xtradb/include/trx0sys.h @@ -41,6 +41,9 @@ Created 3/26/1996 Heikki Tuuri #include "ut0bh.h" #include "read0types.h" #include "page0types.h" +#ifdef WITH_WSREP +#include "trx0xa.h" +#endif /* WITH_WSREP */ /** In a MySQL replication slave, in crash recovery we store the master log file name and position here. */ @@ -341,6 +344,17 @@ UNIV_INTERN void trx_sys_print_mysql_binlog_offset(void); /*===================================*/ +#ifdef WITH_WSREP +/** Update WSREP checkpoint XID in sys header. */ +void +trx_sys_update_wsrep_checkpoint( + const XID* xid, /*!< in: WSREP XID */ + mtr_t* mtr); /*!< in: mtr */ +void +/** Read WSREP checkpoint XID from sys header. */ +trx_sys_read_wsrep_checkpoint( + XID* xid); /*!< out: WSREP XID */ +#endif /* WITH_WSREP */ /*****************************************************************//** Prints to stderr the MySQL master log offset info in the trx system header COMMIT set of fields if the magic number shows it valid and stores it @@ -564,6 +578,22 @@ crash recovery rollbacks a PREPAREd transaction, they are copied back. */ within that file */ #define TRX_SYS_MYSQL_LOG_NAME 12 /*!< MySQL log file name */ +#ifdef WITH_WSREP +/* We hijack TRX_SYS_MYSQL_MASTER_LOG_INFO, it seems to be completely unused + otherwise (see comments for MySQL bug #34058). */ +/** */ +#define TRX_SYS_WSREP_XID_INFO TRX_SYS_MYSQL_MASTER_LOG_INFO +#define TRX_SYS_WSREP_XID_MAGIC_N_FLD 0 +#define TRX_SYS_WSREP_XID_MAGIC_N 0x77737265 + +/* XID field: formatID, gtrid_len, bqual_len, xid_data */ +#define TRX_SYS_WSREP_XID_LEN (4 + 4 + 4 + XIDDATASIZE) +#define TRX_SYS_WSREP_XID_FORMAT 4 +#define TRX_SYS_WSREP_XID_GTRID_LEN 8 +#define TRX_SYS_WSREP_XID_BQUAL_LEN 12 +#define TRX_SYS_WSREP_XID_DATA 16 +#endif /* WITH_WSREP*/ + /** Doublewrite buffer */ /* @{ */ /** The offset of the doublewrite buffer header on the trx system header page */ diff --git a/storage/xtradb/include/trx0trx.h b/storage/xtradb/include/trx0trx.h index a03f7aceafa..86f02f53b52 100644 --- a/storage/xtradb/include/trx0trx.h +++ b/storage/xtradb/include/trx0trx.h @@ -746,6 +746,9 @@ struct trx_struct{ /*------------------------------*/ char detailed_error[256]; /*!< detailed error message for last error, or empty. */ +#ifdef WITH_WSREP + os_event_t wsrep_event; /* event waited for in srv_conc_slot */ +#endif /* WITH_WSREP */ /*------------------------------*/ ulint io_reads; ib_uint64_t io_read; diff --git a/storage/xtradb/lock/lock0lock.c b/storage/xtradb/lock/lock0lock.c index 47d082ed49f..a38656200db 100644 --- a/storage/xtradb/lock/lock0lock.c +++ b/storage/xtradb/lock/lock0lock.c @@ -40,6 +40,9 @@ Created 5/7/1996 Heikki Tuuri #include "trx0sys.h" #include "btr0btr.h" +#ifdef WITH_WSREP +extern my_bool wsrep_debug; +#endif /* Restricts the length of search we will do in the waits-for graph of transactions */ #define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000 @@ -926,6 +929,11 @@ lock_rec_has_to_wait( if (trx != lock2->trx && !lock_mode_compatible(LOCK_MODE_MASK & type_mode, lock_get_mode(lock2))) { +#ifdef WITH_WSREP + if ((type_mode & WSREP_BF) && (lock2->type_mode & WSREP_BF)) { + return FALSE; + } +#endif /* WITH_WSREP */ /* We have somewhat complex rules when gap type record locks cause waits */ @@ -1455,6 +1463,11 @@ lock_rec_has_expl( return(NULL); } +#ifdef WITH_WSREP +static +void +lock_rec_discard(lock_t* in_lock); +#endif #ifdef UNIV_DEBUG /*********************************************************************//** Checks if some other transaction has a lock request in the queue. @@ -1504,6 +1517,27 @@ lock_rec_other_has_expl_req( } #endif /* UNIV_DEBUG */ +#ifdef WITH_WSREP +static void +wsrep_kill_victim(trx_t *trx, lock_t *lock) { + int bf_this = wsrep_thd_is_brute_force(trx->mysql_thd); + int bf_other = + wsrep_thd_is_brute_force(lock->trx->mysql_thd); + if ((bf_this && !bf_other) || + (bf_this && bf_other && wsrep_trx_order_before( + trx->mysql_thd, lock->trx->mysql_thd))) { + + if (lock->trx->que_state == TRX_QUE_LOCK_WAIT) { + if (wsrep_debug) + fprintf(stderr, "WSREP: BF victim waiting\n"); + /* cannot release lock, until our lock + is in the queue*/ + } else if (lock->trx != trx) { + wsrep_innobase_kill_one_trx(trx, lock->trx, TRUE); + } + } +} +#endif /*********************************************************************//** Checks if some other transaction has a conflicting explicit lock request in the queue, so that we have to wait. @@ -1533,6 +1567,9 @@ lock_rec_other_has_conflicting( do { if (lock_rec_has_to_wait(trx, mode, lock, TRUE)) { +#ifdef WITH_WSREP + wsrep_kill_victim(trx, lock); +#endif return(lock); } @@ -1543,6 +1580,9 @@ lock_rec_other_has_conflicting( do { if (lock_rec_has_to_wait(trx, mode, lock, FALSE)) { +#ifdef WITH_WSREP + wsrep_kill_victim(trx, lock); +#endif return(lock); } @@ -1674,6 +1714,9 @@ static lock_t* lock_rec_create( /*============*/ +#ifdef WITH_WSREP + lock_t* c_lock, /* conflicting lock */ +#endif ulint type_mode,/*!< in: lock mode and wait flag, type is ignored and replaced by LOCK_REC */ @@ -1719,6 +1762,11 @@ lock_rec_create( lock->trx = trx; lock->type_mode = (type_mode & ~LOCK_TYPE_MASK) | LOCK_REC; +#ifdef WITH_WSREP + if (wsrep_thd_is_brute_force(trx->mysql_thd)) { + lock->type_mode |= WSREP_BF; + } +#endif /* WITH_WSREP */ lock->index = index; lock->un_member.rec_lock.space = space; @@ -1733,8 +1781,64 @@ lock_rec_create( /* Set the bit corresponding to rec */ lock_rec_set_nth_bit(lock, heap_no); +#ifdef WITH_WSREP + if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { + lock_t *hash = c_lock->hash; + lock_t *prev = NULL; + + while (hash && + wsrep_thd_is_brute_force(hash->trx->mysql_thd) && + wsrep_trx_order_before(hash->trx->mysql_thd, trx->mysql_thd)){ + prev = hash; + hash = hash->hash; + } + lock->hash = hash; + if (prev) { + prev->hash = lock; + } else { + c_lock->hash = lock; + } + /* + * delayed conflict resolution '...kill_one_trx' was not called, + * if victim was waiting for some other lock + */ + if (c_lock && c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) { + c_lock->trx->was_chosen_as_deadlock_victim = TRUE; + + if (wsrep_debug && c_lock->trx->wait_lock != c_lock) { + fprintf(stderr, "WSREP: c_lock != wait lock\n"); + lock_rec_print(stderr, c_lock); + lock_rec_print(stderr, c_lock->trx->wait_lock); + } + + trx->que_state = TRX_QUE_LOCK_WAIT; + lock_set_lock_and_trx_wait(lock, trx); + + lock_cancel_waiting_and_release(c_lock->trx->wait_lock); + + /* trx might not wait for c_lock, but some other lock + does not matter if wait_lock was released above + */ + if (c_lock->trx->wait_lock == c_lock) { + lock_reset_lock_and_trx_wait(lock); + } + + if (wsrep_debug) fprintf( + stderr, + "WSREP: c_lock canceled %llu\n", + (ulonglong) c_lock->trx->id); + + /* have to bail out here to avoid lock_set_lock... */ + return(lock); + } + } else { + HASH_INSERT(lock_t, hash, lock_sys->rec_hash, + lock_rec_fold(space, page_no), lock); + } +#else HASH_INSERT(lock_t, hash, lock_sys->rec_hash, lock_rec_fold(space, page_no), lock); +#endif lock_sys->rec_num++; if (lock_is_wait_not_by_other(type_mode)) { @@ -1755,6 +1859,9 @@ static enum db_err lock_rec_enqueue_waiting( /*=====================*/ +#ifdef WITH_WSREP + lock_t* c_lock, /* conflicting lock */ +#endif ulint type_mode,/*!< in: lock mode this transaction is requesting: LOCK_S or LOCK_X, possibly @@ -1809,9 +1916,18 @@ lock_rec_enqueue_waiting( } if (lock == NULL) { +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && trx->was_chosen_as_deadlock_victim) { + return(DB_DEADLOCK); + } + /* Enqueue the lock request that will wait to be granted */ + lock = lock_rec_create(c_lock, type_mode | LOCK_WAIT, + block, heap_no, index, trx); +#else /* Enqueue the lock request that will wait to be granted */ lock = lock_rec_create(type_mode | LOCK_WAIT, block, heap_no, index, trx); +#endif /*WITH_WSREP */ } else { ut_ad(lock->type_mode & LOCK_WAIT); ut_ad(lock->type_mode & LOCK_CONV_BY_OTHER); @@ -1900,7 +2016,19 @@ lock_rec_add_to_queue( lock_t* other_lock = lock_rec_other_has_expl_req(mode, 0, LOCK_WAIT, block, heap_no, trx); +#ifdef WITH_WSREP + /* this can potentionally assert with wsrep */ + if (wsrep_on(trx->mysql_thd)) { + if (wsrep_debug && other_lock) { + fprintf(stderr, + "WSREP: InnoDB assert ignored\n"); + } + } else { + ut_a(!other_lock); + } +#else ut_a(!other_lock); +#endif /* WITH_WSREP */ } #endif /* UNIV_DEBUG */ @@ -1953,7 +2081,11 @@ lock_rec_add_to_queue( } somebody_waits: +#ifdef WITH_WSREP + return(lock_rec_create(NULL, type_mode, block, heap_no, index, trx)); +#else return(lock_rec_create(type_mode, block, heap_no, index, trx)); +#endif } /** Record locking request status */ @@ -2003,6 +2135,11 @@ lock_rec_lock_fast( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == 0 +#ifdef WITH_WSREP + || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0 + || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP + || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP +#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); lock = lock_rec_get_first_on_page(block); @@ -2011,7 +2148,11 @@ lock_rec_lock_fast( if (lock == NULL) { if (!impl) { +#ifdef WITH_WSREP + lock_rec_create(NULL, mode, block, heap_no, index, trx); +#else lock_rec_create(mode, block, heap_no, index, trx); +#endif } return(LOCK_REC_SUCCESS_CREATED); @@ -2067,6 +2208,9 @@ lock_rec_lock_slow( que_thr_t* thr) /*!< in: query thread */ { trx_t* trx; +#ifdef WITH_WSREP + lock_t *c_lock; +#endif lock_t* lock; ut_ad(mutex_own(&kernel_mutex)); @@ -2078,6 +2222,11 @@ lock_rec_lock_slow( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == 0 +#ifdef WITH_WSREP + || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0 + || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP + || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP +#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP); trx = thr_get_trx(thr); @@ -2106,7 +2255,12 @@ lock_rec_lock_slow( /* The trx already has a strong enough lock on rec: do nothing */ +#ifdef WITH_WSREP + } else if ((c_lock = lock_rec_other_has_conflicting( + mode, block, heap_no, trx))) { +#else } else if (lock_rec_other_has_conflicting(mode, block, heap_no, trx)) { +#endif /* If another transaction has a non-gap conflicting request in the queue, as this transaction does not have a lock strong @@ -2114,8 +2268,13 @@ lock_rec_lock_slow( ut_ad(lock == NULL); enqueue_waiting: +#ifdef WITH_WSREP + return(lock_rec_enqueue_waiting(c_lock,mode, block, heap_no, + lock, index, thr)); +#else return(lock_rec_enqueue_waiting(mode, block, heap_no, lock, index, thr)); +#endif } else if (!impl) { /* Set the requested lock on the record */ @@ -2161,8 +2320,17 @@ lock_rec_lock( || (LOCK_MODE_MASK & mode) == LOCK_X); ut_ad(mode - (LOCK_MODE_MASK & mode) == LOCK_GAP || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP +#ifdef WITH_WSREP + || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == 0 + || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_GAP + || mode - (LOCK_MODE_MASK & mode) - WSREP_BF == LOCK_REC_NOT_GAP +#endif /* WITH_WSREP */ || mode - (LOCK_MODE_MASK & mode) == 0); - +#ifdef WITH_WSREP + if (wsrep_thd_is_brute_force(thr_get_trx(thr)->mysql_thd)) { + mode |= WSREP_BF; + } +#endif /* We try a simplified and faster subroutine for the most common cases */ switch (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) { @@ -3597,6 +3765,26 @@ lock_deadlock_recursive( stderr); } #endif /* UNIV_DEBUG */ +#ifdef WITH_WSREP + if (wsrep_debug) + fputs("WSREP: Deadlock detected\n", stderr); + if (wsrep_thd_is_brute_force(start->mysql_thd) && + wsrep_thd_is_brute_force( + wait_lock->trx->mysql_thd) && + (start != wait_lock->trx)) { + + if (wsrep_trx_order_before( + start->mysql_thd, + wait_lock->trx->mysql_thd)) { + + wait_lock->trx->was_chosen_as_deadlock_victim = TRUE; + lock_cancel_waiting_and_release(wait_lock); + return(LOCK_VICTIM_IS_OTHER); + } else { + return(LOCK_VICTIM_IS_START); + } + } +#endif if (trx_weight_ge(wait_lock->trx, start)) { /* Our recursion starting point @@ -3604,8 +3792,21 @@ lock_deadlock_recursive( choose 'start' as the victim and roll back it */ +#ifdef WITH_WSREP + if (!wsrep_thd_is_brute_force( + start->mysql_thd)) { + return(LOCK_VICTIM_IS_START); + } +#else return(LOCK_VICTIM_IS_START); +#endif } +#ifdef WITH_WSREP + if (wsrep_thd_is_brute_force( + wait_lock->trx->mysql_thd)) { + return(LOCK_VICTIM_IS_START); + } +#endif lock_deadlock_found = TRUE; @@ -3690,6 +3891,9 @@ UNIV_INLINE lock_t* lock_table_create( /*==============*/ +#ifdef WITH_WSREP + lock_t* c_lock, /* conflicting lock */ +#endif dict_table_t* table, /*!< in: database table in dictionary cache */ ulint type_mode,/*!< in: lock mode possibly ORed with LOCK_WAIT */ @@ -3726,7 +3930,25 @@ lock_table_create( lock->un_member.tab_lock.table = table; +#ifdef WITH_WSREP + if (c_lock && wsrep_thd_is_brute_force(trx->mysql_thd)) { + UT_LIST_INSERT_AFTER( + un_member.tab_lock.locks, table->locks, c_lock, lock); + } else { + UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock); + } + + if (c_lock && c_lock->trx->que_state == TRX_QUE_LOCK_WAIT) { + if (wsrep_debug) + fprintf(stderr, "WSREP: table c_lock in wait: %llu\n", + (ulonglong) lock->trx->id); + c_lock->trx->was_chosen_as_deadlock_victim = TRUE; + lock_cancel_waiting_and_release(c_lock); + } + +#else UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock); +#endif if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) { @@ -3872,6 +4094,9 @@ static ulint lock_table_enqueue_waiting( /*=======================*/ +#ifdef WITH_WSREP + lock_t* c_lock, /* conflicting lock */ +#endif ulint mode, /*!< in: lock mode this transaction is requesting */ dict_table_t* table, /*!< in: table */ @@ -3915,7 +4140,14 @@ lock_table_enqueue_waiting( /* Enqueue the lock request that will wait to be granted */ +#ifdef WITH_WSREP + if (trx->was_chosen_as_deadlock_victim) { + return(DB_DEADLOCK); + } + lock = lock_table_create(c_lock, table, mode | LOCK_WAIT, trx); +#else lock = lock_table_create(table, mode | LOCK_WAIT, trx); +#endif /* Check if a deadlock occurs: if yes, remove the lock request and return an error code */ @@ -3978,7 +4210,32 @@ lock_table_other_has_incompatible( && (!lock_mode_compatible(lock_get_mode(lock), mode)) && (wait || !(lock_get_wait(lock)))) { +#ifdef WITH_WSREP + int bf_this = wsrep_thd_is_brute_force(trx->mysql_thd); + int bf_other = wsrep_thd_is_brute_force( + lock->trx->mysql_thd); + if ((bf_this && !bf_other) || + (bf_this && bf_other && + wsrep_trx_order_before( + trx->mysql_thd, lock->trx->mysql_thd) + ) + ) { + if (lock->trx->que_state == TRX_QUE_LOCK_WAIT) { + if (wsrep_debug) fprintf(stderr, + "WSREP: BF victim waiting"); + return(lock); + } else { + if (bf_this && bf_other) + wsrep_innobase_kill_one_trx( + (trx_t *)trx, lock->trx, TRUE); + return(lock); + } + } else { + return(lock); + } +#else return(lock); +#endif } lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock); @@ -4001,6 +4258,9 @@ lock_table( enum lock_mode mode, /*!< in: lock mode */ que_thr_t* thr) /*!< in: query thread */ { +#ifdef WITH_WSREP + lock_t *c_lock; +#endif trx_t* trx; ulint err; @@ -4033,19 +4293,32 @@ lock_table( /* We have to check if the new lock is compatible with any locks other transactions have in the table lock queue. */ +#ifdef WITH_WSREP + if ((c_lock = (lock_t *)lock_table_other_has_incompatible( + trx, LOCK_WAIT, table, mode))) { +#else if (lock_table_other_has_incompatible(trx, LOCK_WAIT, table, mode)) { +#endif /* Another trx has a request on the table in an incompatible mode: this trx may have to wait */ +#ifdef WITH_WSREP + err = lock_table_enqueue_waiting(c_lock, mode | flags, table, thr); +#else err = lock_table_enqueue_waiting(mode | flags, table, thr); +#endif lock_mutex_exit_kernel(); return(err); } +#ifdef WITH_WSREP + lock_table_create(c_lock, table, mode | flags, trx); +#else lock_table_create(table, mode | flags, trx); +#endif ut_a(!flags || mode == LOCK_S || mode == LOCK_X); @@ -4968,6 +5241,7 @@ lock_rec_queue_validate( if (!lock_rec_get_gap(lock) && !lock_get_wait(lock)) { +#ifndef WITH_WSREP enum lock_mode mode; if (lock_get_mode(lock) == LOCK_S) { @@ -4977,6 +5251,7 @@ lock_rec_queue_validate( } ut_a(!lock_rec_other_has_expl_req( mode, 0, 0, block, heap_no, lock->trx)); +#endif /* WITH_WSREP */ } else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) { @@ -5251,6 +5526,9 @@ lock_rec_insert_check_and_lock( lock_t* lock; ulint err; ulint next_rec_heap_no; +#ifdef WITH_WSREP + lock_t *c_lock; +#endif ut_ad(block->frame == page_align(rec)); @@ -5308,15 +5586,28 @@ lock_rec_insert_check_and_lock( had to wait for their insert. Both had waiting gap type lock requests on the successor, which produced an unnecessary deadlock. */ +#ifdef WITH_WSREP + if ((c_lock = lock_rec_other_has_conflicting( + LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION | WSREP_BF, + block, next_rec_heap_no, trx))) { +#else if (lock_rec_other_has_conflicting( LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION, block, next_rec_heap_no, trx)) { +#endif /* Note that we may get DB_SUCCESS also here! */ +#ifdef WITH_WSREP + err = lock_rec_enqueue_waiting(c_lock, LOCK_X | LOCK_GAP + | LOCK_INSERT_INTENTION, + block, next_rec_heap_no, + NULL, index, thr); +#else err = lock_rec_enqueue_waiting(LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION, block, next_rec_heap_no, NULL, index, thr); +#endif /* WITH_WSREP */ } else { err = DB_SUCCESS; } @@ -5400,6 +5691,11 @@ lock_rec_convert_impl_to_expl( implicit lock. Because cannot lock at this moment.*/ if (rec_get_deleted_flag(rec, rec_offs_comp(offsets)) +#ifdef WITH_WSREP + && !wsrep_thd_is_brute_force(impl_trx->mysql_thd) + /* BF-BF conflict is possible if advancing into + lock_rec_other_has_conflicting*/ +#endif /* WITH_WSREP */ && lock_rec_other_has_conflicting( LOCK_X | LOCK_REC_NOT_GAP, block, heap_no, impl_trx)) { diff --git a/storage/xtradb/os/os0file.c b/storage/xtradb/os/os0file.c index 1724e39d342..ce0ebc9a9c6 100644 --- a/storage/xtradb/os/os0file.c +++ b/storage/xtradb/os/os0file.c @@ -96,6 +96,12 @@ UNIV_INTERN os_mutex_t os_file_seek_mutexes[OS_FILE_N_SEEK_MUTEXES]; /* In simulated aio, merge at most this many consecutive i/os */ #define OS_AIO_MERGE_N_CONSECUTIVE 64 +#ifdef WITH_INNODB_DISALLOW_WRITES +#define WAIT_ALLOW_WRITES() os_event_wait(srv_allow_writes_event) +#else +#define WAIT_ALLOW_WRITES() do { } while (0) +#endif /* WITH_INNODB_DISALLOW_WRITES */ + /********************************************************************** InnoDB AIO Implementation: @@ -819,7 +825,9 @@ os_file_create_tmpfile(void) /*========================*/ { FILE* file = NULL; - int fd = innobase_mysql_tmpfile(); + int fd; + WAIT_ALLOW_WRITES(); + fd = innobase_mysql_tmpfile(); if (fd >= 0) { file = fdopen(fd, "w+b"); @@ -1138,6 +1146,7 @@ os_file_create_directory( return (TRUE); #else int rcode; + WAIT_ALLOW_WRITES(); rcode = mkdir(pathname, 0770); @@ -1239,6 +1248,8 @@ try_again: os_file_t file; int create_flag; ibool retry; + if (create_mode != OS_FILE_OPEN && create_mode != OS_FILE_OPEN_RAW) + WAIT_ALLOW_WRITES(); try_again: ut_a(name); @@ -1371,6 +1382,8 @@ os_file_create_simple_no_error_handling_func( int create_flag; ut_a(name); + if (create_mode != OS_FILE_OPEN && create_mode != OS_FILE_OPEN_RAW) + WAIT_ALLOW_WRITES(); if (create_mode == OS_FILE_OPEN) { if (access_type == OS_FILE_READ_ONLY) { @@ -1668,6 +1681,8 @@ try_again: int create_flag; ibool retry; const char* mode_str = NULL; + if (create_mode != OS_FILE_OPEN && create_mode != OS_FILE_OPEN_RAW) + WAIT_ALLOW_WRITES(); DBUG_EXECUTE_IF( "ib_create_table_fail_disk_full", @@ -1841,6 +1856,7 @@ loop: goto loop; #else int ret; + WAIT_ALLOW_WRITES(); ret = unlink(name); @@ -1904,6 +1920,7 @@ loop: goto loop; #else int ret; + WAIT_ALLOW_WRITES(); ret = unlink(name); @@ -1944,6 +1961,7 @@ os_file_rename_func( return(FALSE); #else int ret; + WAIT_ALLOW_WRITES(); ret = rename(oldpath, newpath); @@ -2229,6 +2247,7 @@ os_file_set_eof( HANDLE h = (HANDLE) _get_osfhandle(fileno(file)); return(SetEndOfFile(h)); #else /* __WIN__ */ + WAIT_ALLOW_WRITES(); return(!ftruncate(fileno(file), ftell(file))); #endif /* __WIN__ */ } @@ -2358,6 +2377,7 @@ os_file_flush_func( return(FALSE); #else int ret; + WAIT_ALLOW_WRITES(); #if defined(HAVE_DARWIN_THREADS) # ifndef F_FULLFSYNC @@ -3033,6 +3053,7 @@ retry: return(FALSE); #else ssize_t ret; + WAIT_ALLOW_WRITES(); ret = os_file_pwrite(file, buf, n, offset, offset_high); diff --git a/storage/xtradb/rem/rem0rec.c b/storage/xtradb/rem/rem0rec.c index 6bd40c54a0c..8ea62c32113 100644 --- a/storage/xtradb/rem/rem0rec.c +++ b/storage/xtradb/rem/rem0rec.c @@ -31,6 +31,9 @@ Created 5/30/1994 Heikki Tuuri #include "mtr0mtr.h" #include "mtr0log.h" +#ifdef WITH_WSREP +#include <ha_prototypes.h> +#endif /* WITH_WSREP */ /* PHYSICAL RECORD (OLD STYLE) =========================== @@ -1897,3 +1900,133 @@ rec_print( } } #endif /* !UNIV_HOTBACKUP */ +#ifdef WITH_WSREP +int +wsrep_rec_get_foreign_key( + byte *buf, /* out: extracted key */ + ulint *buf_len, /* in/out: length of buf */ + const rec_t* rec, /* in: physical record */ + dict_index_t* index_for, /* in: index in foreign table */ + dict_index_t* index_ref, /* in: index in referenced table */ + ibool new_protocol) /* in: protocol > 1 */ +{ + const byte* data; + ulint len; + ulint key_len = 0; + ulint i; + uint key_parts; + mem_heap_t* heap = NULL; + ulint offsets_[REC_OFFS_NORMAL_SIZE]; + const ulint* offsets; + + ut_ad(index_for); + ut_ad(index_ref); + + rec_offs_init(offsets_); + offsets = rec_get_offsets(rec, index_for, offsets_, + ULINT_UNDEFINED, &heap); + + ut_ad(rec_offs_validate(rec, NULL, offsets)); + + ut_ad(rec); + + key_parts = dict_index_get_n_unique_in_tree(index_for); + for (i = 0; + i < key_parts && + (index_for->type & DICT_CLUSTERED || i < key_parts - 1); + i++) { + dict_field_t* field_f = + dict_index_get_nth_field(index_for, i); + const dict_col_t* col_f = dict_field_get_col(field_f); + dict_field_t* field_r = + dict_index_get_nth_field(index_ref, i); + const dict_col_t* col_r = dict_field_get_col(field_r); + + data = rec_get_nth_field(rec, offsets, i, &len); + if (key_len + ((len != UNIV_SQL_NULL) ? len + 1 : 1) > + *buf_len) { + fprintf (stderr, + "WSREP: FK key len exceeded %lu %lu %lu\n", + key_len, len, *buf_len); + goto err_out; + } + + if (len == UNIV_SQL_NULL) { + ut_a(!(col_f->prtype & DATA_NOT_NULL)); + *buf++ = 1; + key_len++; + } else if (!new_protocol) { + if (!(col_r->prtype & DATA_NOT_NULL)) { + *buf++ = 0; + key_len++; + } + memcpy(buf, data, len); + wsrep_innobase_mysql_sort( + (int)(col_f->prtype & DATA_MYSQL_TYPE_MASK), + (uint)dtype_get_charset_coll(col_f->prtype), + buf, len); + } else { /* new protocol */ + if (!(col_r->prtype & DATA_NOT_NULL)) { + *buf++ = 0; + key_len++; + } + switch (col_f->mtype) { + case DATA_INT: { + byte* ptr = buf+len; + for (;;) { + ptr--; + *ptr = *data; + if (ptr == buf) { + break; + } + data++; + } + + if (!(col_f->prtype & DATA_UNSIGNED)) { + buf[len-1] = (byte) (buf[len-1] ^ 128); + } + + break; + } + case DATA_VARCHAR: + case DATA_VARMYSQL: + case DATA_CHAR: + case DATA_MYSQL: + /* Copy the actual data */ + ut_memcpy(buf, data, len); + wsrep_innobase_mysql_sort( + (int) + (col_f->prtype & DATA_MYSQL_TYPE_MASK), + (uint) + dtype_get_charset_coll(col_f->prtype), + buf, len); + break; + case DATA_BLOB: + case DATA_BINARY: + memcpy(buf, data, len); + break; + default: + break; + } + + key_len += len; + buf += len; + } + } + + rec_validate(rec, offsets); + + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } + + *buf_len = key_len; + return DB_SUCCESS; + + err_out: + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } + return DB_ERROR; +} +#endif // WITH_WSREP diff --git a/storage/xtradb/row/row0ins.c b/storage/xtradb/row/row0ins.c index fda0c55b5c7..b459019a257 100644 --- a/storage/xtradb/row/row0ins.c +++ b/storage/xtradb/row/row0ins.c @@ -756,6 +756,14 @@ row_ins_invalidate_query_cache( innobase_invalidate_query_cache(thr_get_trx(thr), buf, len); mem_free(buf); } +#ifdef WITH_WSREP +ulint wsrep_append_foreign_key(trx_t *trx, + dict_foreign_t* foreign, + const rec_t* clust_rec, + dict_index_t* clust_index, + ibool referenced, + ibool shared); +#endif /* WITH_WSREP */ /*********************************************************************//** Perform referential actions or checks when a parent row is deleted or updated @@ -1072,6 +1080,16 @@ row_ins_foreign_check_on_constraint( err = row_update_cascade_for_mysql(thr, cascade, foreign->foreign_table); +#ifdef WITH_WSREP + if (err == DB_SUCCESS) { + err = wsrep_append_foreign_key( + thr_get_trx(thr), + foreign, + clust_rec, + clust_index, + FALSE, FALSE); + } +#endif /* WITH_WSREP */ if (foreign->foreign_table->n_foreign_key_checks_running == 0) { fprintf(stderr, "InnoDB: error: table %s has the counter 0" @@ -1408,7 +1426,14 @@ run_again: if (check_ref) { err = DB_SUCCESS; - +#ifdef WITH_WSREP + err = wsrep_append_foreign_key( + thr_get_trx(thr), + foreign, + rec, + check_index, + check_ref, TRUE); +#endif /* WITH_WSREP */ goto end_scan; } else if (foreign->type != 0) { /* There is an ON UPDATE or ON DELETE @@ -1665,6 +1690,9 @@ row_ins_scan_sec_index_for_duplicate( dtuple_t* entry, /*!< in: index entry */ que_thr_t* thr) /*!< in: query thread */ { +#ifdef WITH_WSREP + trx_t* trx = thr_get_trx(thr); +#endif ulint n_unique; ulint i; int cmp; @@ -1718,7 +1746,14 @@ row_ins_scan_sec_index_for_duplicate( offsets = rec_get_offsets(rec, index, offsets, ULINT_UNDEFINED, &heap); +#ifdef WITH_WSREP + /* slave applier must not get duplicate error */ + if (allow_duplicates || + (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd))) { +#else if (allow_duplicates) { +#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for @@ -1836,7 +1871,13 @@ row_ins_duplicate_error_in_clust( sure that in roll-forward we get the same duplicate errors as in original execution */ +#ifdef WITH_WSREP + if (trx->duplicates || + (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd))) { +#else if (trx->duplicates) { +#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for @@ -1880,7 +1921,13 @@ row_ins_duplicate_error_in_clust( offsets = rec_get_offsets(rec, cursor->index, offsets, ULINT_UNDEFINED, &heap); +#ifdef WITH_WSREP + if (trx->duplicates || + (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd))) { +#else if (trx->duplicates) { +#endif /* If the SQL-query will update or replace duplicate key we will take X-lock for diff --git a/storage/xtradb/row/row0upd.c b/storage/xtradb/row/row0upd.c index b2a0eb57669..7d8e63f0058 100644 --- a/storage/xtradb/row/row0upd.c +++ b/storage/xtradb/row/row0upd.c @@ -51,6 +51,9 @@ Created 12/27/1996 Heikki Tuuri #include "pars0sym.h" #include "eval0eval.h" #include "buf0lru.h" +#ifdef WITH_WSREP +extern my_bool wsrep_debug; +#endif /* What kind of latch and lock can we assume when the control comes to @@ -170,6 +173,16 @@ func_exit: return(is_referenced); } +#ifdef WITH_WSREP +ulint wsrep_append_foreign_key(trx_t *trx, + dict_foreign_t* foreign, + const rec_t* clust_rec, + dict_index_t* clust_index, + ibool referenced, + ibool shared); + +#endif /* WITH_WSREP */ + /*********************************************************************//** Checks if possible foreign key constraints hold after a delete of the record under pcur. @@ -283,7 +296,121 @@ row_upd_check_references_constraints( } err = DB_SUCCESS; +func_exit: + if (got_s_lock) { + row_mysql_unfreeze_data_dictionary(trx); + } + + mem_heap_free(heap); + + return(err); +} +#ifdef WITH_WSREP +static +ulint +wsrep_row_upd_check_foreign_constraints( +/*=================================*/ + upd_node_t* node, /*!< in: row update node */ + btr_pcur_t* pcur, /*!< in: cursor positioned on a record; NOTE: the + cursor position is lost in this function! */ + dict_table_t* table, /*!< in: table in question */ + dict_index_t* index, /*!< in: index of the cursor */ + ulint* offsets,/*!< in/out: rec_get_offsets(pcur.rec, index) */ + que_thr_t* thr, /*!< in: query thread */ + mtr_t* mtr) /*!< in: mtr */ +{ + dict_foreign_t* foreign; + mem_heap_t* heap; + dtuple_t* entry; + trx_t* trx; + const rec_t* rec; + ulint n_ext; + ulint err; + ibool got_s_lock = FALSE; + + if (UT_LIST_GET_FIRST(table->foreign_list) == NULL) { + + return(DB_SUCCESS); + } + + trx = thr_get_trx(thr); + + rec = btr_pcur_get_rec(pcur); + ut_ad(rec_offs_validate(rec, index, offsets)); + + heap = mem_heap_create(500); + + entry = row_rec_to_index_entry(ROW_COPY_DATA, rec, index, offsets, + &n_ext, heap); + + mtr_commit(mtr); + + mtr_start(mtr); + + if (trx->dict_operation_lock_mode == 0) { + got_s_lock = TRUE; + + row_mysql_freeze_data_dictionary(trx); + } + + foreign = UT_LIST_GET_FIRST(table->foreign_list); + + while (foreign) { + /* Note that we may have an update which updates the index + record, but does NOT update the first fields which are + referenced in a foreign key constraint. Then the update does + NOT break the constraint. */ + + if (foreign->foreign_index == index + && (node->is_delete + || row_upd_changes_first_fields_binary( + entry, index, node->update, + foreign->n_fields))) { + + if (foreign->referenced_table == NULL) { + dict_table_get(foreign->referenced_table_name_lookup, + FALSE); + } + + if (foreign->referenced_table) { + mutex_enter(&(dict_sys->mutex)); + (foreign->referenced_table + ->n_foreign_key_checks_running)++; + + mutex_exit(&(dict_sys->mutex)); + } + + /* 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 'foreign' from + being dropped while the check is running. */ + + err = row_ins_check_foreign_constraint( + TRUE, foreign, table, entry, thr); + + if (foreign->referenced_table) { + mutex_enter(&(dict_sys->mutex)); + + ut_a(foreign->referenced_table + ->n_foreign_key_checks_running > 0); + + (foreign->referenced_table + ->n_foreign_key_checks_running)--; + + mutex_exit(&(dict_sys->mutex)); + } + + if (err != DB_SUCCESS) { + + goto func_exit; + } + } + + foreign = UT_LIST_GET_NEXT(foreign_list, foreign); + } + + err = DB_SUCCESS; func_exit: if (got_s_lock) { row_mysql_unfreeze_data_dictionary(trx); @@ -293,6 +420,7 @@ func_exit: return(err); } +#endif /* WITH_WSREP */ /*********************************************************************//** Creates an update node for a query graph. @@ -1665,6 +1793,33 @@ row_upd_sec_index_entry( node, &pcur, index->table, index, offsets, thr, &mtr); } +#ifdef WITH_WSREP + if (err == DB_SUCCESS && !referenced) { + ulint* offsets = + rec_get_offsets( + rec, index, NULL, ULINT_UNDEFINED, + &heap); + err = wsrep_row_upd_check_foreign_constraints( + node, &pcur, index->table, + index, offsets, thr, &mtr); + switch (err) { + case DB_SUCCESS: + case DB_NO_REFERENCED_ROW: + err = DB_SUCCESS; + break; + case DB_DEADLOCK: + if (wsrep_debug) + fprintf (stderr, + "WSREP: sec index FK check fail for deadlock"); + break; + default: + fprintf (stderr, + "WSREP: referenced FK check fail: %lu", + err); + break; + } + } +#endif /* WITH_WSREP */ } break; } @@ -1908,6 +2063,30 @@ err_exit: goto err_exit; } } +#ifdef WITH_WSREP + if (!referenced) { + err = wsrep_row_upd_check_foreign_constraints( + node, pcur, table, index, offsets, thr, mtr); + switch (err) { + case DB_SUCCESS: + case DB_NO_REFERENCED_ROW: + err = DB_SUCCESS; + break; + case DB_DEADLOCK: + if (wsrep_debug) fprintf (stderr, + "WSREP: insert FK check fail for deadlock"); + break; + default: + fprintf (stderr, + "WSREP: referenced FK check fail: %lu", + err); + break; + } + if (err != DB_SUCCESS) { + goto err_exit; + } + } +#endif /* WITH_WSREP */ } mtr_commit(mtr); @@ -2115,6 +2294,9 @@ row_upd_del_mark_clust_rec( btr_pcur_t* pcur; btr_cur_t* btr_cur; ulint err; +#ifdef WITH_WSREP + rec_t* rec; +#endif /* WITH_WSREP */ ut_ad(node); ut_ad(dict_index_is_clust(index)); @@ -2131,15 +2313,44 @@ row_upd_del_mark_clust_rec( /* Mark the clustered index record deleted; we do not have to check locks, because we assume that we have an x-lock on the record */ +#ifdef WITH_WSREP + rec = btr_cur_get_rec(btr_cur); +#endif /* WITH_WSREP */ + err = btr_cur_del_mark_set_clust_rec( BTR_NO_LOCKING_FLAG, btr_cur_get_block(btr_cur), +#ifdef WITH_WSREP + rec, index, offsets, TRUE, thr, mtr); +#else btr_cur_get_rec(btr_cur), index, offsets, TRUE, thr, mtr); +#endif /* WITH_WSREP */ if (err == DB_SUCCESS && referenced) { /* NOTE that the following call loses the position of pcur ! */ err = row_upd_check_references_constraints( node, pcur, index->table, index, offsets, thr, mtr); } +#ifdef WITH_WSREP + if (err == DB_SUCCESS && !referenced) { + err = wsrep_row_upd_check_foreign_constraints( + node, pcur, index->table, index, offsets, thr, mtr); + switch (err) { + case DB_SUCCESS: + case DB_NO_REFERENCED_ROW: + err = DB_SUCCESS; + break; + case DB_DEADLOCK: + if (wsrep_debug) fprintf (stderr, + "WSREP: clust rec FK check fail for deadlock"); + break; + default: + fprintf (stderr, + "WSREP: clust rec referenced FK check fail: %lu", + err); + break; + } + } +#endif /* WITH_WSREP */ mtr_commit(mtr); diff --git a/storage/xtradb/srv/srv0srv.c b/storage/xtradb/srv/srv0srv.c index 6edfbaa7755..1a3667f45e3 100644 --- a/storage/xtradb/srv/srv0srv.c +++ b/storage/xtradb/srv/srv0srv.c @@ -99,6 +99,10 @@ ulong innobase_thd_get_thread_id(const void* thd); /* 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; @@ -232,6 +236,10 @@ srv_printf_innodb_monitor() will request mutex acquisition with mutex_enter(), which will wait until it gets the mutex. */ #define MUTEX_NOWAIT(mutex_skipped) ((mutex_skipped) < MAX_MUTEX_NOWAIT) +#ifdef WITH_INNODB_DISALLOW_WRITES +UNIV_INTERN os_event_t srv_allow_writes_event; +#endif /* WITH_INNODB_DISALLOW_WRITES */ + /** The sort order table of the MySQL latin1_swedish_ci character set collation */ UNIV_INTERN const byte* srv_latin1_ordering; @@ -376,6 +384,9 @@ struct srv_conc_slot_struct{ free to proceed; but reserved may still be TRUE at that point */ +#ifdef WITH_WSREP + void *thd; /*!< to see priority */ +#endif UT_LIST_NODE_T(srv_conc_slot_t) srv_conc_queue; /*!< queue node */ }; @@ -1183,8 +1194,20 @@ srv_init(void) conc_slot->reserved = FALSE; conc_slot->event = os_event_create(NULL); ut_a(conc_slot->event); +#ifdef WITH_WSREP + conc_slot->thd = NULL; +#endif /* WITH_WSREP */ } +#ifdef WITH_INNODB_DISALLOW_WRITES + /* Writes have to be enabled on init or else we hang. Thus, we + always set the event here regardless of innobase_disallow_writes. + That flag will always be 0 at this point because it isn't settable + via my.cnf or command line arg. */ + srv_allow_writes_event = os_event_create(NULL); + os_event_set(srv_allow_writes_event); +#endif /* WITH_INNODB_DISALLOW_WRITES */ + /* Initialize some INFORMATION SCHEMA internal structures */ trx_i_s_cache_init(trx_i_s_cache); } @@ -1233,6 +1256,23 @@ srv_general_init(void) /* Maximum allowable purge history length. <=0 means 'infinite'. */ UNIV_INTERN ulong srv_max_purge_lag = 0; +#ifdef WITH_WSREP +UNIV_INTERN +void +wsrep_srv_conc_cancel_wait( +/*==================*/ + trx_t* trx) /*!< in: transaction object associated with the + thread */ +{ + os_fast_mutex_lock(&srv_conc_mutex); + if (trx->wsrep_event) { + if (wsrep_debug) + fprintf(stderr, "WSREP: conc slot cancel\n"); + os_event_set(trx->wsrep_event); + } + os_fast_mutex_unlock(&srv_conc_mutex); +} +#endif /* WITH_WSREP */ /*********************************************************************//** Puts an OS thread to wait if there are too many concurrent threads (>= srv_thread_concurrency) inside InnoDB. The threads wait in a FIFO queue. */ @@ -1350,6 +1390,18 @@ srv_conc_enter_innodb( } #endif +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd)) { + srv_conc_force_enter_innodb(trx); + return; + } + if (wsrep_on(trx->mysql_thd) && + wsrep_trx_is_aborting(trx->mysql_thd)) { + srv_conc_force_enter_innodb(trx); + return; + } +#endif os_fast_mutex_lock(&srv_conc_mutex); retry: if (trx->declared_to_be_inside_innodb) { @@ -1443,6 +1495,9 @@ retry: /* Add to the queue */ slot->reserved = TRUE; slot->wait_ended = FALSE; +#ifdef WITH_WSREP + slot->thd = trx->mysql_thd; +#endif UT_LIST_ADD_LAST(srv_conc_queue, srv_conc_queue, slot); @@ -1450,6 +1505,19 @@ retry: srv_conc_n_waiting_threads++; +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + wsrep_trx_is_aborting(trx->mysql_thd)) { + srv_conc_n_waiting_threads--; + os_fast_mutex_unlock(&srv_conc_mutex); + if (wsrep_debug) + fprintf(stderr, "srv_conc_enter due to MUST_ABORT"); + trx->declared_to_be_inside_innodb = TRUE; + trx->n_tickets_to_enter_innodb = SRV_FREE_TICKETS_TO_ENTER; + return; + } + trx->wsrep_event = slot->event; +#endif /* WITH_WSREP */ os_fast_mutex_unlock(&srv_conc_mutex); /* Go to wait for the event; when a thread leaves InnoDB it will @@ -1472,6 +1540,9 @@ retry: thd_wait_begin(trx->mysql_thd, THD_WAIT_USER_LOCK); os_event_wait(slot->event); thd_wait_end(trx->mysql_thd); +#ifdef WITH_WSREP + trx->wsrep_event = NULL; +#endif /* WITH_WSREP */ trx->op_info = ""; @@ -1489,6 +1560,9 @@ retry: incremented the thread counter on behalf of this thread */ slot->reserved = FALSE; +#ifdef WITH_WSREP + slot->thd = NULL; +#endif UT_LIST_REMOVE(srv_conc_queue, srv_conc_queue, slot); @@ -1574,6 +1648,9 @@ srv_conc_force_exit_innodb( trx->n_tickets_to_enter_innodb = 0; if (srv_conc_n_threads < (lint)srv_thread_concurrency) { +#ifdef WITH_WSREP + srv_conc_slot_t* wsrep_slot; +#endif /* Look for a slot where a thread is waiting and no other thread has yet released the thread */ @@ -1583,6 +1660,19 @@ srv_conc_force_exit_innodb( slot = UT_LIST_GET_NEXT(srv_conc_queue, slot); } +#ifdef WITH_WSREP + /* look for aborting trx, they must be released asap */ + wsrep_slot= slot; + while (wsrep_slot && (wsrep_slot->wait_ended == TRUE || + !wsrep_trx_is_aborting(wsrep_slot->thd))) { + wsrep_slot = UT_LIST_GET_NEXT(srv_conc_queue, wsrep_slot); + } + if (wsrep_slot) { + slot = wsrep_slot; + if (wsrep_debug) + fprintf(stderr, "WSREP: releasing aborting thd\n"); + } +#endif if (slot != NULL) { slot->wait_ended = TRUE; @@ -1959,7 +2049,20 @@ srv_suspend_mysql_thread( if (lock_wait_timeout < 100000000 && wait_time > (double) lock_wait_timeout) { +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + wsrep_thd_is_brute_force(trx->mysql_thd)) { + fprintf(stderr, + "WSREP: BF long lock wait ended after %.f sec\n", + wait_time); + srv_print_innodb_monitor = FALSE; + srv_print_innodb_lock_monitor = FALSE; + } else { +#endif trx->error_state = DB_LOCK_WAIT_TIMEOUT; +#ifdef WITH_WSREP + } +#endif } if (trx_is_interrupted(trx)) { @@ -2720,6 +2823,27 @@ exit_func: OS_THREAD_DUMMY_RETURN; } +#ifdef WITH_WSREP +/*********************************************************************//** +check if lock timeout was for priority thread, +as a side effect trigger lock monitor +@return false for regular lock timeout */ +static ibool +wsrep_is_BF_lock_timeout( +/*====================*/ + srv_slot_t* slot) /* in: lock slot to check for lock priority */ +{ + if (wsrep_on(thr_get_trx(slot->thr)->mysql_thd) && + wsrep_thd_is_brute_force((thr_get_trx(slot->thr))->mysql_thd)) { + fprintf(stderr, "WSREP: BF lock wait long\n"); + srv_print_innodb_monitor = TRUE; + srv_print_innodb_lock_monitor = TRUE; + os_event_set(srv_lock_timeout_thread_event); + return TRUE; + } + return FALSE; + } +#endif /* WITH_WSREP */ /*********************************************************************//** A thread which wakes up threads whose lock wait may have lasted too long. @return a dummy parameter */ @@ -2788,8 +2912,14 @@ loop: granted: in that case do nothing */ if (trx->wait_lock) { +#ifdef WITH_WSREP + if (!wsrep_is_BF_lock_timeout(slot)) { +#endif lock_cancel_waiting_and_release( trx->wait_lock); +#ifdef WITH_WSREP + } +#endif } } } @@ -2906,7 +3036,20 @@ loop: if (sync_array_print_long_waits(&waiter, &sema) && sema == old_sema && os_thread_eq(waiter, old_waiter)) { +#if defined(WITH_WSREP) && defined(WITH_INNODB_DISALLOW_WRITES) + if (srv_allow_writes_event->is_set) { +#endif /* WITH_WSREP */ fatal_cnt++; +#if defined(WITH_WSREP) && defined(WITH_INNODB_DISALLOW_WRITES) + } else { + fprintf(stderr, + "WSREP: avoiding InnoDB self crash due to long " + "semaphore wait of > %lu seconds\n" + "Server is processing SST donor operation, " + "fatal_cnt now: %lu", + (ulong) srv_fatal_semaphore_wait_threshold, fatal_cnt); + } +#endif /* WITH_WSREP */ if (fatal_cnt > 10) { fprintf(stderr, diff --git a/storage/xtradb/trx/trx0roll.c b/storage/xtradb/trx/trx0roll.c index b55471959ce..3db63469cbe 100644 --- a/storage/xtradb/trx/trx0roll.c +++ b/storage/xtradb/trx/trx0roll.c @@ -42,6 +42,9 @@ Created 3/26/1996 Heikki Tuuri #include "row0mysql.h" #include "lock0lock.h" #include "pars0pars.h" +#ifdef WITH_WSREP +#include "ha_prototypes.h" +#endif /* WITH_WSREP */ /** This many pages must be undone before a truncate is tried within rollback */ @@ -147,6 +150,12 @@ trx_rollback_for_mysql( trx->op_info = ""; +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->was_chosen_as_deadlock_victim) { + trx->was_chosen_as_deadlock_victim = FALSE; + } +#endif return(err); } @@ -174,6 +183,12 @@ trx_rollback_last_sql_stat_for_mysql( trx->op_info = ""; +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->was_chosen_as_deadlock_victim) { + trx->was_chosen_as_deadlock_victim = FALSE; + } +#endif return(err); } @@ -1123,6 +1138,12 @@ trx_rollback( srv_que_task_enqueue_low(thr); /* srv_que_task_enqueue_low(thr2); */ } +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->was_chosen_as_deadlock_victim) { + trx->was_chosen_as_deadlock_victim = FALSE; + } +#endif } /****************************************************************//** @@ -1281,6 +1302,12 @@ trx_finish_rollback_off_kernel( sig = next_sig; } +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->was_chosen_as_deadlock_victim) { + trx->was_chosen_as_deadlock_victim = FALSE; + } +#endif } /*********************************************************************//** diff --git a/storage/xtradb/trx/trx0sys.c b/storage/xtradb/trx/trx0sys.c index c40bf02a7a2..59b7da4083d 100644 --- a/storage/xtradb/trx/trx0sys.c +++ b/storage/xtradb/trx/trx0sys.c @@ -44,6 +44,10 @@ Created 3/26/1996 Heikki Tuuri #include "os0file.h" #include "read0read.h" +#ifdef WITH_WSREP +#include "ha_prototypes.h" /* wsrep_is_wsrep_xid() */ +#endif /* */ + /** The file format tag structure with id and name. */ struct file_format_struct { ulint id; /*!< id of the file format */ @@ -958,6 +962,89 @@ trx_sys_print_mysql_binlog_offset(void) mtr_commit(&mtr); } +#ifdef WITH_WSREP + +void +trx_sys_update_wsrep_checkpoint( + const XID* xid, /*!< in: transaction XID */ + mtr_t* mtr) /*!< in: mtr */ +{ + trx_sysf_t* sys_header; + + ut_ad(xid && mtr); + ut_a(xid->formatID == -1 || wsrep_is_wsrep_xid(xid)); + + sys_header = trx_sysf_get(mtr); + if (mach_read_from_4(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_MAGIC_N_FLD) + != TRX_SYS_WSREP_XID_MAGIC_N) { + mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_MAGIC_N_FLD, + TRX_SYS_WSREP_XID_MAGIC_N, + MLOG_4BYTES, mtr); + } + + mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_FORMAT, + (int)xid->formatID, + MLOG_4BYTES, mtr); + mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_GTRID_LEN, + (int)xid->gtrid_length, + MLOG_4BYTES, mtr); + mlog_write_ulint(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_BQUAL_LEN, + (int)xid->bqual_length, + MLOG_4BYTES, mtr); + mlog_write_string(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_DATA, + (const unsigned char*) xid->data, + XIDDATASIZE, mtr); + +} + +void +trx_sys_read_wsrep_checkpoint(XID* xid) +/*===================================*/ +{ + trx_sysf_t* sys_header; + mtr_t mtr; + ulint magic; + + ut_ad(xid); + + mtr_start(&mtr); + + sys_header = trx_sysf_get(&mtr); + + if ((magic = mach_read_from_4(sys_header + TRX_SYS_WSREP_XID_INFO + + TRX_SYS_WSREP_XID_MAGIC_N_FLD)) + != TRX_SYS_WSREP_XID_MAGIC_N) { + memset(xid, 0, sizeof(*xid)); + xid->formatID = -1; + trx_sys_update_wsrep_checkpoint(xid, &mtr); + mtr_commit(&mtr); + return; + } + + xid->formatID = (int)mach_read_from_4( + sys_header + + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_FORMAT); + xid->gtrid_length = (int)mach_read_from_4( + sys_header + + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_GTRID_LEN); + xid->bqual_length = (int)mach_read_from_4( + sys_header + + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_BQUAL_LEN); + ut_memcpy(xid->data, + sys_header + TRX_SYS_WSREP_XID_INFO + TRX_SYS_WSREP_XID_DATA, + XIDDATASIZE); + + mtr_commit(&mtr); +} + +#endif /* WITH_WSREP */ + /*****************************************************************//** Reads the log coordinates at the given offset in the trx sys header. */ static diff --git a/storage/xtradb/trx/trx0trx.c b/storage/xtradb/trx/trx0trx.c index a17f8abdad0..f7924763e17 100644 --- a/storage/xtradb/trx/trx0trx.c +++ b/storage/xtradb/trx/trx0trx.c @@ -211,6 +211,9 @@ trx_create( /* Remember to free the vector explicitly. */ trx->autoinc_locks = ib_vector_create( mem_heap_create(sizeof(ib_vector_t) + sizeof(void*) * 4), 4); +#ifdef WITH_WSREP + trx->wsrep_event = NULL; +#endif /* WITH_WSREP */ return(trx); } @@ -755,6 +758,11 @@ trx_start_low( trx->id = trx_sys_get_new_trx_id(); +#ifdef WITH_WSREP + memset(&trx->xid, 0, sizeof(trx->xid)); + trx->xid.formatID = -1; +#endif /* WITH_WSREP */ + /* The initial value for trx->no: IB_ULONGLONG_MAX is used in read_view_open_now: */ @@ -909,6 +917,14 @@ trx_write_serialisation_history( mutex_exit(&rseg->mutex); +#ifdef WITH_WSREP + /* Update latest MySQL wsrep XID in trx sys header. */ + if (wsrep_is_wsrep_xid(&trx->xid)) + { + trx_sys_update_wsrep_checkpoint(&trx->xid, &mtr); + } +#endif /* WITH_WSREP */ + /* Update the latest MySQL binlog name and offset info in trx sys header if MySQL binlogging is on or the database server is a MySQL replication slave */ @@ -1139,6 +1155,12 @@ trx_commit_off_kernel( ut_ad(UT_LIST_GET_LEN(trx->wait_thrs) == 0); ut_ad(UT_LIST_GET_LEN(trx->trx_locks) == 0); +#ifdef WITH_WSREP + if (wsrep_on(trx->mysql_thd) && + trx->was_chosen_as_deadlock_victim) { + trx->was_chosen_as_deadlock_victim = FALSE; + } +#endif UT_LIST_REMOVE(trx_list, trx_sys->trx_list, trx); trx->error_state = DB_SUCCESS; diff --git a/support-files/CMakeLists.txt b/support-files/CMakeLists.txt index fde4746df16..6fbd52a64eb 100644 --- a/support-files/CMakeLists.txt +++ b/support-files/CMakeLists.txt @@ -41,7 +41,7 @@ ELSE() SET(inst_location ${INSTALL_SUPPORTFILESDIR}) ENDIF() -FOREACH(inifile my-huge my-innodb-heavy-4G my-large my-medium my-small) +FOREACH(inifile my-huge my-innodb-heavy-4G my-large my-medium my-small wsrep) CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/${inifile}.cnf.sh ${CMAKE_CURRENT_BINARY_DIR}/${inifile}.${ini_file_extension} @ONLY) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/${inifile}.${ini_file_extension} @@ -93,6 +93,12 @@ IF(UNIX) DESTINATION ${inst_location} COMPONENT SupportFiles PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) + CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/wsrep_notify.sh + ${CMAKE_CURRENT_BINARY_DIR}/wsrep_notify @ONLY) + INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/wsrep_notify + DESTINATION ${inst_location} COMPONENT SupportFiles + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ + GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) IF (INSTALL_SYSCONFDIR) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/mysql-log-rotate DESTINATION ${INSTALL_SYSCONFDIR}/logrotate.d diff --git a/support-files/build-tags b/support-files/build-tags index b5386dc79c3..f42fae218d2 100755 --- a/support-files/build-tags +++ b/support-files/build-tags @@ -1,12 +1,17 @@ #! /bin/sh rm -f TAGS -filter='\.cc$\|\.c$\|\.h$\|\.yy$' +filter='\.cc$\|\.c$\|\.h$\|\.yy\|\.ic\|.ih$' -list="find . -type f" +#list="find . -type f" bzr root >/dev/null 2>/dev/null && list="bzr ls --from-root -R --kind=file --versioned" $list |grep $filter |while read f; do etags -o TAGS --append $f done + +(cd storage/galera && svn ls -R) | grep $filter | while read f; +do + etags -o TAGS --append storage/galera/$f +done diff --git a/support-files/mysql.spec.sh b/support-files/mysql.spec.sh index bac22fc96a9..1fcb9be71da 100644 --- a/support-files/mysql.spec.sh +++ b/support-files/mysql.spec.sh @@ -68,6 +68,14 @@ # # ---------------------------------------------------------------------------- +# wsrep builds +# ---------------------------------------------------------------------------- +%if %{defined with_wsrep} +%define mysql_version @VERSION@_wsrep_@WSREP_API_VERSION@.@WSREP_PATCH_VERSION@ +%define wsrep_version @WSREP_VERSION@ +%endif + +# ---------------------------------------------------------------------------- # Commercial builds # ---------------------------------------------------------------------------- %if %{undefined commercial} @@ -115,6 +123,13 @@ %endif # ---------------------------------------------------------------------------- +# Packager +# ---------------------------------------------------------------------------- +%if %{undefined mysql_packager} +%define mysql_packager MySQL Build Team <build@mysql.com> +%endif + +# ---------------------------------------------------------------------------- # Distribution support # ---------------------------------------------------------------------------- %if %{undefined distro_specific} @@ -283,6 +298,10 @@ documentation and the manual for more information. ############################################################################## %package -n MySQL-server%{product_suffix} +%if %{defined with_wsrep} +Version: %{mysql_version} +#Release: %{wsrep_version}.%{release} +%endif Summary: MySQL: a very fast and reliable SQL database server Group: Applications/Databases Requires: %{distro_requires} @@ -313,6 +332,9 @@ and the manual for more information. This package includes the MySQL server binary as well as related utilities to run and administer a MySQL server. +%if %{defined with_wsrep} +Built with wsrep patch %{wsrep_version}. +%endif If you want to access and work with the database, you have to install package "MySQL-client%{product_suffix}" as well! @@ -381,6 +403,7 @@ This package contains the shared libraries (*.so*) which certain languages and applications need to dynamically load and use MySQL. # ---------------------------------------------------------------------------- +%if %{undefined with_wsrep} %package -n MySQL-embedded%{product_suffix} Summary: MySQL - Embedded library Group: Applications/Databases @@ -403,6 +426,7 @@ The API is identical for the embedded MySQL version and the client/server version. For a description of MySQL see the base MySQL RPM or http://www.mysql.com/ +%endif ############################################################################## %prep @@ -478,6 +502,9 @@ mkdir debug -DMYSQL_UNIX_ADDR="%{mysqldatadir}/mysql.sock" \ -DFEATURE_SET="%{feature_set}" \ -DCOMPILATION_COMMENT="%{compilation_comment_debug}" \ +%if %{defined with_wsrep} + -DWITH_WSREP=1 \ +%endif -DMYSQL_SERVER_SUFFIX="%{server_suffix}" echo BEGIN_DEBUG_CONFIG ; egrep '^#define' include/config.h ; echo END_DEBUG_CONFIG make ${MAKE_JFLAG} VERBOSE=1 @@ -493,6 +520,9 @@ mkdir release -DMYSQL_UNIX_ADDR="%{mysqldatadir}/mysql.sock" \ -DFEATURE_SET="%{feature_set}" \ -DCOMPILATION_COMMENT="%{compilation_comment_release}" \ +%if %{defined with_wsrep} + -DWITH_WSREP=1 \ +%endif -DMYSQL_SERVER_SUFFIX="%{server_suffix}" echo BEGIN_NORMAL_CONFIG ; egrep '^#define' include/config.h ; echo END_NORMAL_CONFIG make ${MAKE_JFLAG} VERBOSE=1 @@ -555,11 +585,20 @@ install -m 755 $MBD/release/support-files/mysql.server $RBR%{_sysconfdir}/init.d # Create a symlink "rcmysql", pointing to the init.script. SuSE users # will appreciate that, as all services usually offer this. -ln -s %{_sysconfdir}/init.d/mysql $RBR%{_sbindir}/rcmysql +ln -sf %{_sysconfdir}/init.d/mysql $RBR%{_sbindir}/rcmysql + +%if %{defined with_wsrep} +# Create a wsrep_sst_rsync_wan symlink. +install -d $RBR%{_bindir} +ln -sf wsrep_sst_rsync $RBR%{_bindir}/wsrep_sst_rsync_wan +%endif # Touch the place where the my.cnf config file might be located # Just to make sure it's in the file list and marked as a config file touch $RBR%{_sysconfdir}/my.cnf +%if %{defined with_wsrep} +touch $RBR%{_sysconfdir}/wsrep.cnf +%endif # Install SELinux files in datadir install -m 600 $MBD/%{src_dir}/support-files/RHEL4-SElinux/mysql.{fc,te} \ @@ -1018,6 +1057,11 @@ echo "=====" >> $STATUS_HISTORY %doc %{src_dir}/Docs/INFO_SRC* %doc release/Docs/INFO_BIN* %doc release/support-files/my-*.cnf +%if %{defined with_wsrep} +%doc %{src_dir}/Docs/README-wsrep +%doc release/support-files/wsrep.cnf +%doc release/support-files/wsrep_notify +%endif %doc %attr(644, root, root) %{_infodir}/mysql.info* @@ -1051,6 +1095,9 @@ echo "=====" >> $STATUS_HISTORY %doc %attr(644, root, man) %{_mandir}/man1/resolveip.1* %ghost %config(noreplace,missingok) %{_sysconfdir}/my.cnf +%if %{defined with_wsrep} +%ghost %config(noreplace,missingok) %{_sysconfdir}/wsrep.cnf +%endif %attr(755, root, root) %{_bindir}/innochecksum %attr(755, root, root) %{_bindir}/my_print_defaults @@ -1077,6 +1124,13 @@ echo "=====" >> $STATUS_HISTORY %attr(755, root, root) %{_bindir}/replace %attr(755, root, root) %{_bindir}/resolve_stack_dump %attr(755, root, root) %{_bindir}/resolveip +%if %{defined with_wsrep} +%attr(755, root, root) %{_bindir}/wsrep_sst_common +%attr(755, root, root) %{_bindir}/wsrep_sst_mysqldump +%attr(755, root, root) %{_bindir}/wsrep_sst_rsync +%attr(755, root, root) %{_bindir}/wsrep_sst_rsync_wan +%attr(755, root, root) %{_bindir}/wsrep_sst_xtrabackup +%endif %attr(755, root, root) %{_sbindir}/mysqld %attr(755, root, root) %{_sbindir}/mysqld-debug @@ -1155,8 +1209,10 @@ echo "=====" >> $STATUS_HISTORY %defattr(-, root, root, 0755) %attr(-, root, root) %{_datadir}/mysql-test %attr(755, root, root) %{_bindir}/mysql_client_test +%if %{undefined with_wsrep} %attr(755, root, root) %{_bindir}/mysql_client_test_embedded %attr(755, root, root) %{_bindir}/mysqltest_embedded +%endif %doc %attr(644, root, man) %{_mandir}/man1/mysql_client_test.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql-stress-test.pl.1* %doc %attr(644, root, man) %{_mandir}/man1/mysql-test-run.pl.1* @@ -1164,11 +1220,13 @@ echo "=====" >> $STATUS_HISTORY %doc %attr(644, root, man) %{_mandir}/man1/mysqltest_embedded.1* # ---------------------------------------------------------------------------- +%if %{undefined with_wsrep} %files -n MySQL-embedded%{product_suffix} %defattr(-, root, root, 0755) %attr(755, root, root) %{_bindir}/mysql_embedded %attr(644, root, root) %{_libdir}/mysql/libmysqld.a %attr(644, root, root) %{_libdir}/mysql/libmysqld-debug.a +%endif ############################################################################## # The spec file changelog only includes changes made to the spec file @@ -1188,6 +1246,10 @@ echo "=====" >> $STATUS_HISTORY - Make sure newly added "SPECIFIC-ULN/" directory does not disturb packaging. +* Wed Dec 07 2011 Alexey Yurchenko <alexey.yurchenko@codership.com> + +- wsrep-related cleanups. + * Wed Sep 28 2011 Joerg Bruehe <joerg.bruehe@oracle.com> - Fix duplicate mentioning of "mysql_plugin" and its manual page, @@ -1240,7 +1302,6 @@ echo "=====" >> $STATUS_HISTORY - Fix bug#12561297: Added the MySQL embedded binary * Thu Jul 07 2011 Joerg Bruehe <joerg.bruehe@oracle.com> - - Fix bug#45415: "rpm upgrade recreates test database" Let the creation of the "test" database happen only during a new installation, not in an RPM upgrade. |