diff options
49 files changed, 1848 insertions, 143 deletions
diff --git a/.bzrignore b/.bzrignore index 6b18d09723b..be6b6d47d31 100644 --- a/.bzrignore +++ b/.bzrignore @@ -699,7 +699,6 @@ ma_test_recovery.output man/*.1 maria-win.patch maria_log.00000* -maria_log_control merge/*.ds? merge/*.vcproj missing @@ -1961,3 +1960,8 @@ client/strings_def.h libmysql/strings_def.h libmysql_r/strings_def.h storage/maria/aria_log_control +CPackConfig.cmake +CPackSourceConfig.cmake +win/nmake_cache.txt +*.manifest +*.resource.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index ea44226781a..9b5b46fa340 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,6 +114,9 @@ ENDIF(ENABLED_DEBUG_SYNC) SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DENABLED_DEBUG_SYNC") SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DENABLED_DEBUG_SYNC") +SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") +SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") + # in some places we use DBUG_OFF SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DDBUG_OFF") SET(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} -DDBUG_OFF") @@ -247,16 +250,15 @@ IF(WITHOUT_DYNAMIC_PLUGINS) MESSAGE("Dynamic plugins are disabled.") ENDIF(WITHOUT_DYNAMIC_PLUGINS) -FILE(GLOB STORAGE_SUBDIRS storage/*) +FILE(GLOB STORAGE_SUBDIRS storage/* plugin/*) FOREACH(SUBDIR ${STORAGE_SUBDIRS}) - FILE(RELATIVE_PATH DIRNAME ${PROJECT_SOURCE_DIR}/storage ${SUBDIR}) IF (EXISTS ${SUBDIR}/CMakeLists.txt) # Check MYSQL_STORAGE_ENGINE macro is present - FILE(STRINGS ${SUBDIR}/CMakeLists.txt HAVE_STORAGE_ENGINE REGEX MYSQL_STORAGE_ENGINE) + FILE(STRINGS ${SUBDIR}/CMakeLists.txt HAVE_STORAGE_ENGINE REGEX "MYSQL_(STORAGE_ENGINE|PLUGIN)") IF(HAVE_STORAGE_ENGINE) # Extract name of engine from HAVE_STORAGE_ENGINE - STRING(REGEX REPLACE ".*MYSQL_STORAGE_ENGINE\\((.*\)\\).*" - "\\1" ENGINE_NAME ${HAVE_STORAGE_ENGINE}) + STRING(REGEX REPLACE ".*MYSQL_(STORAGE_ENGINE|PLUGIN)\\((.*\)\\).*" + "\\2" ENGINE_NAME ${HAVE_STORAGE_ENGINE}) STRING(TOUPPER ${ENGINE_NAME} ENGINE) STRING(TOLOWER ${ENGINE_NAME} ENGINE_LOWER) @@ -265,21 +267,23 @@ FOREACH(SUBDIR ${STORAGE_SUBDIRS}) # build as shared library (dynamic). IF(EXISTS ${SUBDIR}/plug.in) FILE(READ ${SUBDIR}/plug.in PLUGIN_FILE_CONTENT) - STRING (REGEX MATCH "MYSQL_PLUGIN_DYNAMIC" MYSQL_PLUGIN_DYNAMIC ${PLUGIN_FILE_CONTENT}) + IF (PLUGIN_FILE_CONTENT MATCHES "MYSQL_PLUGIN_DYNAMIC\\(${ENGINE_LOWER}") + STRING (REGEX REPLACE + ".*MYSQL_PLUGIN_DYNAMIC\\(${ENGINE_LOWER},[ \\t]*\\[?([a-zA-Z0-9_]+/)*([a-zA-Z0-9_]+).*" + "\\2" MYSQL_PLUGIN_DYNAMIC ${PLUGIN_FILE_CONTENT}) + ELSE (PLUGIN_FILE_CONTENT MATCHES "MYSQL_PLUGIN_DYNAMIC\\(${ENGINE_LOWER}") + SET (MYSQL_PLUGIN_DYNAMIC "") + ENDIF(PLUGIN_FILE_CONTENT MATCHES "MYSQL_PLUGIN_DYNAMIC\\(${ENGINE_LOWER}") + IF (PLUGIN_FILE_CONTENT MATCHES "MYSQL_PLUGIN_STATIC\\(${ENGINE_LOWER}") + STRING (REGEX REPLACE + ".*MYSQL_PLUGIN_STATIC\\(${ENGINE_LOWER},[ \\t]*\\[?([a-zA-Z0-9_]+/)*([a-zA-Z0-9_]+).*" + "\\2" + MYSQL_PLUGIN_STATIC ${PLUGIN_FILE_CONTENT}) + ELSE (PLUGIN_FILE_CONTENT MATCHES "MYSQL_PLUGIN_STATIC\\(${ENGINE_LOWER}") + SET (MYSQL_PLUGIN_STATIC "") + ENDIF(PLUGIN_FILE_CONTENT MATCHES "MYSQL_PLUGIN_STATIC\\(${ENGINE_LOWER}") STRING (REGEX MATCH "MYSQL_PLUGIN_MANDATORY" MYSQL_PLUGIN_MANDATORY ${PLUGIN_FILE_CONTENT}) - STRING (REGEX MATCH "MYSQL_PLUGIN_STATIC" MYSQL_PLUGIN_STATIC ${PLUGIN_FILE_CONTENT}) - - # - # XTRADB is located in storage/xtradb, but it says everywhere it is 'innobase' (e.g. - # it declares 'builtin_innobase_plugin', not builtin_xtradb_plugin). - # Extract the intended plugin name from MYSQL_STORAGE_ENGINE definition and use it - # where appropriate. - STRING (REGEX MATCH "MYSQL_STORAGE_ENGINE.[a-z]*" PLUGIN_NAME ${PLUGIN_FILE_CONTENT}) - STRING (REGEX REPLACE "MYSQL_STORAGE_ENGINE.(.*)" "\\1" PLUGIN_NAME ${PLUGIN_NAME}) - # Also remember this "xtradb"/"innobase" name discrepancy for libmysqld/CMakeLists.txt: - SET (plugin_dir_${PLUGIN_NAME} ${DIRNAME}) - IF(MYSQL_PLUGIN_MANDATORY) SET(WITH_${ENGINE}_STORAGE_ENGINE TRUE) ENDIF(MYSQL_PLUGIN_MANDATORY) @@ -293,15 +297,17 @@ FOREACH(SUBDIR ${STORAGE_SUBDIRS}) ENDIF(WITH_${ENGINE}_STORAGE_ENGINE AND MYSQL_PLUGIN_STATIC) IF (ENGINE_BUILD_TYPE STREQUAL "STATIC") - SET (maria_plugin_defs "${maria_plugin_defs},builtin_maria_${PLUGIN_NAME}_plugin") - SET (MYSQLD_STATIC_ENGINE_LIBS ${MYSQLD_STATIC_ENGINE_LIBS} ${PLUGIN_NAME}) + SET (maria_plugin_defs "${maria_plugin_defs},builtin_maria_${ENGINE_LOWER}_plugin") + SET (MYSQLD_STATIC_ENGINE_LIBS ${MYSQLD_STATIC_ENGINE_LIBS} ${MYSQL_PLUGIN_STATIC}) + SET (MYSQLD_STATIC_ENGINES ${MYSQLD_STATIC_ENGINES} ${ENGINE}) SET (STORAGE_ENGINE_DEFS "${STORAGE_ENGINE_DEFS} -DWITH_${ENGINE}_STORAGE_ENGINE") SET (WITH_${ENGINE}_STORAGE_ENGINE TRUE) - SET (${ENGINE}_DIR ${DIRNAME}) + SET (${ENGINE}_DIR ${SUBDIR}) ENDIF (ENGINE_BUILD_TYPE STREQUAL "STATIC") ENDIF(EXISTS ${SUBDIR}/plug.in) IF(NOT ENGINE_BUILD_TYPE STREQUAL "NONE") + SET (${ENGINE}_LIB ${MYSQL_PLUGIN_${ENGINE_BUILD_TYPE}}) LIST(APPEND ${ENGINE_BUILD_TYPE}_ENGINE_DIRECTORIES ${SUBDIR}) ENDIF(NOT ENGINE_BUILD_TYPE STREQUAL "NONE") diff --git a/configure.in b/configure.in index ffdcd937c11..a7d8f557e75 100644 --- a/configure.in +++ b/configure.in @@ -865,7 +865,7 @@ AC_HEADER_STDC AC_HEADER_SYS_WAIT AC_CHECK_HEADERS(fcntl.h fenv.h float.h floatingpoint.h fpu_control.h \ ieeefp.h limits.h memory.h pwd.h select.h fnmatch.h \ - stdlib.h stddef.h sys/stat.h \ + stdlib.h stddef.h sys/stat.h sys/sockio.h \ strings.h string.h synch.h sys/mman.h sys/socket.h netinet/in.h arpa/inet.h \ sys/timeb.h sys/types.h sys/un.h sys/vadvise.h sys/wait.h term.h \ unistd.h utime.h sys/utime.h termio.h termios.h sched.h crypt.h alloca.h \ diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index 77d141d5282..801cab0ffa6 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -16,13 +16,27 @@ #ifndef _my_plugin_h #define _my_plugin_h - /* On Windows, exports from DLL need to be declared -*/ -#if (defined(_WIN32) && defined(MYSQL_DYNAMIC_PLUGIN)) -#define MYSQL_PLUGIN_EXPORT extern "C" __declspec(dllexport) -#else + Also, plugin needs to be declared as extern "C" because MSVC + unlike other compilers, uses C++ mangling for variables not only + for functions. +*/ +#if defined(_MSC_VER) +#if defined(MYSQL_DYNAMIC_PLUGIN) + #ifdef __cplusplus + #define MYSQL_PLUGIN_EXPORT extern "C" __declspec(dllexport) + #else + #define MYSQL_PLUGIN_EXPORT __declspec(dllexport) + #endif +#else /* MYSQL_DYNAMIC_PLUGIN */ + #ifdef __cplusplus + #define MYSQL_PLUGIN_EXPORT extern "C" + #else + #define MYSQL_PLUGIN_EXPORT + #endif +#endif /*MYSQL_DYNAMIC_PLUGIN */ +#else /*_MSC_VER */ #define MYSQL_PLUGIN_EXPORT #endif diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index 412902f5746..4c6aa2f3a7f 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -86,15 +86,13 @@ FOREACH(rpath ${VIO_SOURCES}) SET(LIB_SOURCES ${LIB_SOURCES} ../vio/${rpath}) ENDFOREACH(rpath) -FOREACH (ENGINE_LIB ${MYSQLD_STATIC_ENGINE_LIBS}) - INCLUDE(${CMAKE_SOURCE_DIR}/storage/${plugin_dir_${ENGINE_LIB}}/CMakeLists.txt) - STRING(TOUPPER ${ENGINE_LIB} ENGINE_LIB_UPPER) - SET(ENGINE_DIR ${${ENGINE_LIB_UPPER}_DIR}) - INCLUDE(${CMAKE_SOURCE_DIR}/storage/${ENGINE_DIR}/CMakeLists.txt) - FOREACH(rpath ${${ENGINE_LIB_UPPER}_SOURCES}) - SET(LIB_SOURCES ${LIB_SOURCES} ${CMAKE_SOURCE_DIR}/storage/${ENGINE_DIR}/${rpath}) +SET (ENGINE_BUILD_TYPE "STATIC") +FOREACH (ENGINE ${MYSQLD_STATIC_ENGINES}) + INCLUDE(${${ENGINE}_DIR}/CMakeLists.txt) + FOREACH(rpath ${${ENGINE}_SOURCES}) + SET(LIB_SOURCES ${LIB_SOURCES} ${${ENGINE}_DIR}/${rpath}) ENDFOREACH(rpath) -ENDFOREACH(ENGINE_LIB) +ENDFOREACH(ENGINE) SET(SOURCE_SUBLIBS FALSE) @@ -162,15 +160,14 @@ IF(MSVC AND CMAKE_SIZEOF_VOID_P MATCHES 8) ENDIF() # Add any additional libraries requested by engine(s) -FOREACH (ENGINE_LIB ${MYSQLD_STATIC_ENGINE_LIBS}) - STRING(TOUPPER ${ENGINE_LIB} ENGINE_LIB_UPPER) - IF(${ENGINE_LIB_UPPER}_LIBS) - TARGET_LINK_LIBRARIES(mysqlserver ${${ENGINE_LIB_UPPER}_LIBS}) - ENDIF(${ENGINE_LIB_UPPER}_LIBS) -ENDFOREACH(ENGINE_LIB) +FOREACH (ENGINE ${MYSQLD_STATIC_ENGINES}) + IF(${ENGINE}_LIBS) + TARGET_LINK_LIBRARIES(mysqlserver ${${ENGINE}_LIBS}) + ENDIF(${ENGINE}_LIBS) +ENDFOREACH(ENGINE) ADD_LIBRARY(libmysqld SHARED cmake_dummy.c libmysqld.def) ADD_DEPENDENCIES(libmysqld mysqlserver) -TARGET_LINK_LIBRARIES(libmysqld mysqlserver wsock32) +TARGET_LINK_LIBRARIES(libmysqld mysqlserver wsock32 iphlpapi) MYSQL_INSTALL_TARGETS(mysqlserver libmysqld DESTINATION lib COMPONENT Embedded) diff --git a/mysql-test/include/default_mysqld.cnf b/mysql-test/include/default_mysqld.cnf index e46c3bc3c17..a1b477c51dd 100644 --- a/mysql-test/include/default_mysqld.cnf +++ b/mysql-test/include/default_mysqld.cnf @@ -15,6 +15,8 @@ max_heap_table_size= 1M loose-skip-innodb loose-skip-pbxt +loose-skip-feedback +loose-feedback-user-info= mysql-test loose-innodb_data_file_path= ibdata1:10M:autoextend diff --git a/mysql-test/r/feedback_plugin_install.result b/mysql-test/r/feedback_plugin_install.result new file mode 100644 index 00000000000..4b3b0226fae --- /dev/null +++ b/mysql-test/r/feedback_plugin_install.result @@ -0,0 +1,13 @@ +install plugin feedback soname 'feedback.so'; +select plugin_status from information_schema.plugins where plugin_name='feedback'; +plugin_status +ACTIVE +select * from information_schema.feedback where variable_name like 'feed%' + and variable_name not like '%_uid'; +VARIABLE_NAME VARIABLE_VALUE +FEEDBACK 1.0 +FEEDBACK_SEND_RETRY_WAIT 60 +FEEDBACK_SEND_TIMEOUT 60 +FEEDBACK_URL http://mariadb.org/feedback_plugin/post +FEEDBACK_USER_INFO mysql-test +uninstall plugin feedback; diff --git a/mysql-test/r/feedback_plugin_load.result b/mysql-test/r/feedback_plugin_load.result new file mode 100644 index 00000000000..bc02b920a11 --- /dev/null +++ b/mysql-test/r/feedback_plugin_load.result @@ -0,0 +1,11 @@ +select plugin_status from information_schema.plugins where plugin_name='feedback'; +plugin_status +ACTIVE +select * from information_schema.feedback where variable_name like 'feed%' + and variable_name not like '%_uid'; +VARIABLE_NAME VARIABLE_VALUE +FEEDBACK 1.0 +FEEDBACK_SEND_RETRY_WAIT 60 +FEEDBACK_SEND_TIMEOUT 60 +FEEDBACK_URL http://mariadb.org/feedback_plugin/post +FEEDBACK_USER_INFO mysql-test diff --git a/mysql-test/r/feedback_plugin_send.result b/mysql-test/r/feedback_plugin_send.result new file mode 100644 index 00000000000..22379e26248 --- /dev/null +++ b/mysql-test/r/feedback_plugin_send.result @@ -0,0 +1,15 @@ +select plugin_status from information_schema.plugins where plugin_name='feedback'; +plugin_status +ACTIVE +select * from information_schema.feedback where variable_name like 'feed%' + and variable_name not like '%_uid'; +VARIABLE_NAME VARIABLE_VALUE +FEEDBACK 1.0 +FEEDBACK_SEND_RETRY_WAIT 60 +FEEDBACK_SEND_TIMEOUT 60 +FEEDBACK_URL http://mariadb.org/feedback_plugin/post +FEEDBACK_USER_INFO mysql-test +feedback plugin: report to 'http://mariadb.org/feedback_plugin/post' was sent +feedback plugin: server replied 'ok' +feedback plugin: report to 'http://mariadb.org/feedback_plugin/post' was sent +feedback plugin: server replied 'ok' diff --git a/mysql-test/t/feedback_plugin_install.opt b/mysql-test/t/feedback_plugin_install.opt new file mode 100644 index 00000000000..a711ae94e69 --- /dev/null +++ b/mysql-test/t/feedback_plugin_install.opt @@ -0,0 +1 @@ +--loose-feedback diff --git a/mysql-test/t/feedback_plugin_install.test b/mysql-test/t/feedback_plugin_install.test new file mode 100644 index 00000000000..81343c436c3 --- /dev/null +++ b/mysql-test/t/feedback_plugin_install.test @@ -0,0 +1,15 @@ +--source include/not_embedded.inc + +if (`select length('$FEEDBACK_SO') = 0`) { + skip No feedback plugin; +} + +--replace_regex /\.dll/.so/ +eval install plugin feedback soname '$FEEDBACK_SO'; +select plugin_status from information_schema.plugins where plugin_name='feedback'; +--replace_result https http +--sorted_result +select * from information_schema.feedback where variable_name like 'feed%' + and variable_name not like '%_uid'; +uninstall plugin feedback; + diff --git a/mysql-test/t/feedback_plugin_load.opt b/mysql-test/t/feedback_plugin_load.opt new file mode 100644 index 00000000000..5fbb2f83954 --- /dev/null +++ b/mysql-test/t/feedback_plugin_load.opt @@ -0,0 +1,2 @@ +--loose-feedback +--plugin-load=$FEEDBACK_SO diff --git a/mysql-test/t/feedback_plugin_load.test b/mysql-test/t/feedback_plugin_load.test new file mode 100644 index 00000000000..5ad301667b4 --- /dev/null +++ b/mysql-test/t/feedback_plugin_load.test @@ -0,0 +1,10 @@ +if (`select count(*) = 0 from information_schema.plugins where plugin_name = 'feedback' and plugin_status='active'`) +{ + --skip Feedback plugin is not active +} + +select plugin_status from information_schema.plugins where plugin_name='feedback'; +--replace_result https http +--sorted_result +select * from information_schema.feedback where variable_name like 'feed%' + and variable_name not like '%_uid'; diff --git a/mysql-test/t/feedback_plugin_send.test b/mysql-test/t/feedback_plugin_send.test new file mode 100644 index 00000000000..b49c0d0e252 --- /dev/null +++ b/mysql-test/t/feedback_plugin_send.test @@ -0,0 +1,24 @@ +source t/feedback_plugin_load.test; +source include/big_test.inc; + +if (!$MTR_FEEDBACK_PLUGIN) { + skip MTR_FEEDBACK_PLUGIN is not set; +} + +# +# Yep. The plugin waits 5 minutes before sending anything, +# and there's no way to force it to send anything sooner. +# Let's wait, and hope that mtr is started with --parallel and +# is doing some work in other workers. +# +sleep 310; +source include/restart_mysqld.inc; + +replace_result https http; +perl; + $log_error= $ENV{'MYSQLTEST_VARDIR'} . '/log/mysqld.1.err'; + open(LOG, '<', $log_error) or die "open(< $log_error): $!"; + /feedback plugin:.*/ && print "$&\n" while $_=<LOG>; + close LOG; +EOF + diff --git a/mysql-test/t/fulltext_plugin.test b/mysql-test/t/fulltext_plugin.test index 31978dadc51..0e2f53d5b15 100644 --- a/mysql-test/t/fulltext_plugin.test +++ b/mysql-test/t/fulltext_plugin.test @@ -3,7 +3,8 @@ # # BUG#39746 - Debug flag breaks struct definition (server crash) # -INSTALL PLUGIN simple_parser SONAME 'mypluglib.so'; +--replace_result .dll .so +eval INSTALL PLUGIN simple_parser SONAME '$MYPLUGLIB_SO'; CREATE TABLE t1(a TEXT, b TEXT, FULLTEXT(a) WITH PARSER simple_parser); ALTER TABLE t1 ADD FULLTEXT(b) WITH PARSER simple_parser; DROP TABLE t1; diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index 9ab19222caf..7bed7b6a548 100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -48,4 +48,5 @@ SET(MYSYS_SOURCES array.c charset-def.c charset.c checksum.c default.c default_ IF(NOT SOURCE_SUBLIBS) ADD_LIBRARY(mysys ${MYSYS_SOURCES}) + TARGET_LINK_LIBRARIES(mysys IPHLPAPI) ENDIF(NOT SOURCE_SUBLIBS) diff --git a/mysys/my_gethwaddr.c b/mysys/my_gethwaddr.c index 90908bd1c0d..bcc231eaf7e 100644 --- a/mysys/my_gethwaddr.c +++ b/mysys/my_gethwaddr.c @@ -16,11 +16,22 @@ /* get hardware address for an interface */ /* if there are many available, any non-zero one can be used */ +#define DONT_DEFINE_VOID /* windows includes break if we do */ #include "mysys_priv.h" #include <m_string.h> #ifndef MAIN +static my_bool memcpy_and_test(uchar *to, uchar *from, uint len) +{ + uint i, res= 1; + + for (i= 0; i < len; i++) + if ((*to++= *from++)) + res= 0; + return res; +} + #ifdef __FreeBSD__ #include <net/ethernet.h> @@ -32,11 +43,10 @@ my_bool my_gethwaddr(uchar *to) { size_t len; - char *buf, *next, *end; + uchar *buf, *next, *end, *addr; struct if_msghdr *ifm; struct sockaddr_dl *sdl; - int res=1, mib[6]={CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0}; - char zero_array[ETHER_ADDR_LEN] = {0}; + int res= 1, mib[6]= {CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0}; if (sysctl(mib, 6, NULL, &len, NULL, 0) == -1) goto err; @@ -52,9 +62,9 @@ my_bool my_gethwaddr(uchar *to) ifm = (struct if_msghdr *)next; if (ifm->ifm_type == RTM_IFINFO) { - sdl= (struct sockaddr_dl *)(ifm + 1); - memcpy(to, LLADDR(sdl), ETHER_ADDR_LEN); - res= memcmp(to, zero_array, ETHER_ADDR_LEN) ? 0 : 1; + sdl = (struct sockaddr_dl *)(ifm + 1); + addr= LLADDR(sdl); + res= memcpy_and_test(to, addr, ETHER_ADDR_LEN); } } @@ -62,40 +72,94 @@ err: return res; } -#elif __linux__ - +#elif defined(__linux__) || defined(__sun__) #include <net/if.h> #include <sys/ioctl.h> -#include <net/ethernet.h> +#include <net/if_arp.h> +#ifdef HAVE_SYS_SOCKIO_H +#include <sys/sockio.h> +#endif + +#define ETHER_ADDR_LEN 6 my_bool my_gethwaddr(uchar *to) { int fd, res= 1; - struct ifreq ifr; - char zero_array[ETHER_ADDR_LEN] = {0}; + struct ifreq ifr[32]; + struct ifconf ifc; + + ifc.ifc_req= ifr; + ifc.ifc_len= sizeof(ifr); fd = socket(AF_INET, SOCK_DGRAM, 0); if (fd < 0) goto err; - bzero(&ifr, sizeof(ifr)); - strnmov(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name) - 1); - - do + if (ioctl(fd, SIOCGIFCONF, (char*)&ifc) >= 0) { - if (ioctl(fd, SIOCGIFHWADDR, &ifr) >= 0) + uint i; + for (i= 0; res && i < ifc.ifc_len / sizeof(ifr[0]); i++) { - memcpy(to, &ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN); - res= memcmp(to, zero_array, ETHER_ADDR_LEN) ? 0 : 1; +#ifdef SIOCGIFHWADDR + if (ioctl(fd, SIOCGIFHWADDR, &ifr[i]) >= 0) + res= memcpy_and_test(to, (uchar *)&ifr[i].ifr_hwaddr.sa_data, + ETHER_ADDR_LEN); +#else + /* + A bug in OpenSolaris prevents non-root from getting a mac address: + http://bugs.opensolaris.org/bugdatabase/view_bug.do?bug_id=4720634 + + Thus, we'll use an alternative method and extract the address from the + arp table. + */ + struct arpreq arpr; + arpr.arp_pa= ifr[i].ifr_addr; + + if (ioctl(fd, SIOCGARP, (char*)&arpr) >= 0) + res= memcpy_and_test(to, (uchar *)&arpr.arp_ha.sa_data, + ETHER_ADDR_LEN); +#endif } - } while (res && (errno == 0 || errno == ENODEV) && ifr.ifr_name[3]++ < '6'); + } close(fd); err: return res; } -#else /* FreeBSD elif linux */ +#elif defined(_WIN32) +#include <winsock2.h> +#include <iphlpapi.h> + +#define ETHER_ADDR_LEN 6 + +my_bool my_gethwaddr(uchar *to) +{ + my_bool res= 1; + + IP_ADAPTER_INFO *info= NULL; + ULONG info_len= 0; + + if (GetAdaptersInfo(info, &info_len) != ERROR_BUFFER_OVERFLOW) + goto err; + + info= alloca(info_len); + + if (GetAdaptersInfo(info, &info_len) != NO_ERROR) + goto err; + + while (info && res) + { + if (info->Type == MIB_IF_TYPE_ETHERNET && + info->AddressLength == ETHER_ADDR_LEN) + res= memcpy_and_test(to, info->Address, ETHER_ADDR_LEN); + } + +err: + return res; +} + +#else /* neither FreeBSD nor linux not Windows */ /* just fail */ my_bool my_gethwaddr(uchar *to __attribute__((unused))) { @@ -114,7 +178,7 @@ int main(int argc __attribute__((unused)),char **argv) printf("my_gethwaddr failed with errno %d\n", errno); exit(1); } - for (i=0; i < sizeof(mac); i++) + for (i= 0; i < sizeof(mac); i++) { if (i) printf(":"); printf("%02x", mac[i]); diff --git a/plugin/feedback/CMakeLists.txt b/plugin/feedback/CMakeLists.txt new file mode 100644 index 00000000000..a94232a4698 --- /dev/null +++ b/plugin/feedback/CMakeLists.txt @@ -0,0 +1,11 @@ +INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql ${CMAKE_SOURCE_DIR}/regex + ${CMAKE_SOURCE_DIR}/extra/yassl/include) + +SET(FEEDBACK_SOURCES feedback.cc sender_thread.cc + url_base.cc url_http.cc utils.cc) + +SET(FEEDBACK_LIBS Ws2_32) + +MYSQL_PLUGIN(FEEDBACK) diff --git a/plugin/feedback/Makefile.am b/plugin/feedback/Makefile.am new file mode 100644 index 00000000000..7d2a61d593f --- /dev/null +++ b/plugin/feedback/Makefile.am @@ -0,0 +1,18 @@ +pkgplugindir = $(pkglibdir)/plugin +INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \ + -I$(top_srcdir)/regex -I$(top_srcdir)/sql + +EXTRA_LTLIBRARIES = feedback.la libfeedback.la +pkgplugin_LTLIBRARIES = @plugin_feedback_shared_target@ +feedback_la_LDFLAGS = -module -rpath $(pkgplugindir) -L$(top_builddir)/libservices -lmysqlservices +feedback_la_CXXFLAGS = -shared -DMYSQL_DYNAMIC_PLUGIN +feedback_la_SOURCES = feedback.cc utils.cc url_base.cc url_http.cc \ + sender_thread.cc + +noinst_LTLIBRARIES = @plugin_feedback_static_target@ +libfeedback_la_SOURCES= feedback.cc utils.cc url_base.cc url_http.cc \ + sender_thread.cc + +noinst_HEADERS = feedback.h +EXTRA_DIST = CMakeLists.txt plug.in + diff --git a/plugin/feedback/feedback.cc b/plugin/feedback/feedback.cc new file mode 100644 index 00000000000..056484ab46e --- /dev/null +++ b/plugin/feedback/feedback.cc @@ -0,0 +1,355 @@ +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "feedback.h" + +/* MySQL functions/variables not declared in mysql_priv.h */ +int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond); +int fill_status(THD *thd, TABLE_LIST *tables, COND *cond); +extern ST_SCHEMA_TABLE schema_tables[]; + +namespace feedback { + +char server_uid_buf[SERVER_UID_SIZE+1]; ///< server uid will be written here + +/* backing store for system variables */ +static char *server_uid= server_uid_buf, *url; +char *user_info; +ulong send_timeout, send_retry_wait; + +/** + these three are used to communicate the shutdown signal to the + background thread +*/ +pthread_mutex_t sleep_mutex; +pthread_cond_t sleep_condition; +volatile bool shutdown_plugin; +static pthread_t sender_thread; + +Url **urls; ///< list of urls to send the report to +uint url_count; + +ST_SCHEMA_TABLE *i_s_feedback; ///< table descriptor for our I_S table + +/* + the column names *must* match column names in GLOBAL_VARIABLES and + GLOBAL_STATUS tables otherwise condition pushdown below will not work +*/ +static ST_FIELD_INFO feedback_fields[] = +{ + {"VARIABLE_NAME", 255, MYSQL_TYPE_STRING, 0, 0, 0, 0}, + {"VARIABLE_VALUE", 1024, MYSQL_TYPE_STRING, 0, 0, 0, 0}, + {0, 0, MYSQL_TYPE_NULL, 0, 0, 0, 0} +}; + +static COND * const OOM= (COND*)1; + +/** + Generate the COND tree for the condition pushdown + + This function takes a list of strings and generates an Item tree + corresponding to the following expression: + + field LIKE str1 OR field LIKE str2 OR field LIKE str3 OR ... + + where 'field' is the first field in the table - VARIABLE_NAME field - + and str1, str2... are strings from the list. + + This condition is used to filter the selected rows, emulating + + SELECT * FROM INFORMATION_SCHEMA.GLOBAL_VARIABLES WHERE ... +*/ +static COND* make_cond(THD *thd, TABLE_LIST *tables, LEX_STRING *filter) +{ + Item_cond_or *res= NULL; + Name_resolution_context nrc; + const char *db= tables->db, *table= tables->alias, + *field= tables->table->field[0]->field_name; + CHARSET_INFO *cs= &my_charset_latin1; + + if (!filter->str) + return 0; + + nrc.init(); + nrc.resolve_in_table_list_only(tables); + + res= new Item_cond_or(); + if (!res) + return OOM; + + for (; filter->str; filter++) + { + Item_field *fld= new Item_field(&nrc, db, table, field); + Item_string *pattern= new Item_string(filter->str, filter->length, cs); + Item_string *escape= new Item_string("\\", 1, cs); + + if (!fld || !pattern || !escape) + return OOM; + + Item_func_like *like= new Item_func_like(fld, pattern, escape, 0); + + if (!like) + return OOM; + + res->add(like); + } + + if (res->fix_fields(thd, (Item**)&res)) + return OOM; + + return res; +} + +/** + System variables that we want to see in the feedback report +*/ +static LEX_STRING vars_filter[]= { + {C_STRING_WITH_LEN("auto\\_increment%")}, + {C_STRING_WITH_LEN("binlog\\_format")}, + {C_STRING_WITH_LEN("character\\_set\\_%")}, + {C_STRING_WITH_LEN("collation%")}, + {C_STRING_WITH_LEN("engine\\_condition\\_pushdown")}, + {C_STRING_WITH_LEN("event\\_scheduler")}, + {C_STRING_WITH_LEN("feedback\\_%")}, + {C_STRING_WITH_LEN("ft\\_m%")}, + {C_STRING_WITH_LEN("have\\_%")}, + {C_STRING_WITH_LEN("%\\_size")}, + {C_STRING_WITH_LEN("%\\_length%")}, + {C_STRING_WITH_LEN("%\\_timeout")}, + {C_STRING_WITH_LEN("large\\_%")}, + {C_STRING_WITH_LEN("lc_time_names")}, + {C_STRING_WITH_LEN("log")}, + {C_STRING_WITH_LEN("log_bin")}, + {C_STRING_WITH_LEN("log_output")}, + {C_STRING_WITH_LEN("log_slow_queries")}, + {C_STRING_WITH_LEN("log_slow_time")}, + {C_STRING_WITH_LEN("lower_case%")}, + {C_STRING_WITH_LEN("max_allowed_packet")}, + {C_STRING_WITH_LEN("max_connections")}, + {C_STRING_WITH_LEN("max_prepared_stmt_count")}, + {C_STRING_WITH_LEN("max_sp_recursion_depth")}, + {C_STRING_WITH_LEN("max_user_connections")}, + {C_STRING_WITH_LEN("max_write_lock_count")}, + {C_STRING_WITH_LEN("myisam_recover_options")}, + {C_STRING_WITH_LEN("myisam_repair_threads")}, + {C_STRING_WITH_LEN("myisam_stats_method")}, + {C_STRING_WITH_LEN("myisam_use_mmap")}, + {C_STRING_WITH_LEN("net\\_%")}, + {C_STRING_WITH_LEN("new")}, + {C_STRING_WITH_LEN("old%")}, + {C_STRING_WITH_LEN("optimizer%")}, + {C_STRING_WITH_LEN("profiling")}, + {C_STRING_WITH_LEN("query_cache%")}, + {C_STRING_WITH_LEN("secure_auth")}, + {C_STRING_WITH_LEN("slow_launch_time")}, + {C_STRING_WITH_LEN("sql%")}, + {C_STRING_WITH_LEN("storage_engine")}, + {C_STRING_WITH_LEN("sync_binlog")}, + {C_STRING_WITH_LEN("table_definition_cache")}, + {C_STRING_WITH_LEN("table_open_cache")}, + {C_STRING_WITH_LEN("thread_handling")}, + {C_STRING_WITH_LEN("time_zone")}, + {C_STRING_WITH_LEN("timed_mutexes")}, + {C_STRING_WITH_LEN("version%")}, + {0, 0} +}; + +/** + Status variables that we want to see in the feedback report + + (empty list = no WHERE condition) +*/ +static LEX_STRING status_filter[]= {{0, 0}}; + +/** + Fill our I_S table with data + + This function works by invoking fill_variables() and + fill_status() of the corresponding I_S tables - to have + their data UNION-ed in the same target table. + After that it invokes our own fill_* functions + from the utils.cc - to get the data that aren't available in the + I_S.GLOBAL_VARIABLES and I_S.GLOBAL_STATUS. +*/ +int fill_feedback(THD *thd, TABLE_LIST *tables, COND *unused) +{ + int res; + COND *cond; + + tables->schema_table= schema_tables + SCH_GLOBAL_VARIABLES; + cond= make_cond(thd, tables, vars_filter); + res= (cond == OOM) ? 1 : fill_variables(thd, tables, cond); + + tables->schema_table= schema_tables + SCH_GLOBAL_STATUS; + if (!res) + { + cond= make_cond(thd, tables, status_filter); + res= (cond == OOM) ? 1 : fill_status(thd, tables, cond); + } + + tables->schema_table= i_s_feedback; + res= res || fill_plugin_version(thd, tables) + || fill_misc_data(thd, tables) + || fill_linux_info(thd, tables); + + return res; +} + +/** + plugin initialization function +*/ +static int init(void *p) +{ + i_s_feedback= (ST_SCHEMA_TABLE*) p; + /* initialize the I_S descriptor structure */ + i_s_feedback->fields_info= feedback_fields; ///< field descriptor + i_s_feedback->fill_table= fill_feedback; ///< how to fill the I_S table + i_s_feedback->idx_field1 = 0; ///< virtual index on the 1st col + + if (calculate_server_uid(server_uid_buf)) + return 1; + + prepare_linux_info(); + + url_count= 0; + if (*url) + { + // now we split url on spaces and store them in Url objects + int slot; + char *s, *e; + + for (s= url, url_count= 1; *s; s++) + if (*s == ' ') + url_count++; + + urls= (Url **)my_malloc(url_count*sizeof(Url*), MYF(MY_WME)); + if (!urls) + return 1; + + for (s= url, e = url+1, slot= 0; e[-1]; e++) + if (*e == 0 || *e == ' ') + { + if (e > s && (urls[slot]= Url::create(s, e - s))) + slot++; + else + { + if (e > s) + sql_print_error("feedback plugin: invalid url '%.*s'", (int)(e-s), s); + url_count--; + } + s= e + 1; + } + + // create a background thread to handle urls, if any + if (url_count) + { + pthread_mutex_init(&sleep_mutex, 0); + pthread_cond_init(&sleep_condition, 0); + shutdown_plugin= false; + + pthread_attr_t attr; + pthread_attr_init(&attr); + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); + if (pthread_create(&sender_thread, &attr, background_thread, 0) != 0) + { + sql_print_error("feedback plugin: failed to start a background thread"); + return 1; + } + } + else + my_free(urls, MYF(0)); + } + + return 0; +} + +/** + plugin deinitialization function +*/ +static int free(void *p) +{ + if (url_count) + { + pthread_mutex_lock(&sleep_mutex); + shutdown_plugin= true; + pthread_cond_signal(&sleep_condition); + pthread_mutex_unlock(&sleep_mutex); + pthread_join(sender_thread, NULL); + + pthread_mutex_destroy(&sleep_mutex); + pthread_cond_destroy(&sleep_condition); + + for (uint i= 0; i < url_count; i++) + delete urls[i]; + my_free(urls, MYF(0)); + } + return 0; +} + +#ifdef HAVE_OPENSSL +#define DEFAULT_PROTO "https://" +#else +#define DEFAULT_PROTO "http://" +#endif + +static MYSQL_SYSVAR_STR(server_uid, server_uid, + PLUGIN_VAR_READONLY | PLUGIN_VAR_NOCMDOPT, + "Automatically calculated server unique id hash.", NULL, NULL, 0); +static MYSQL_SYSVAR_STR(user_info, user_info, + PLUGIN_VAR_READONLY | PLUGIN_VAR_RQCMDARG, + "User specified string that will be included in the feedback report.", + NULL, NULL, ""); +static MYSQL_SYSVAR_STR(url, url, PLUGIN_VAR_READONLY | PLUGIN_VAR_RQCMDARG, + "Space separated URLs to send the feedback report to.", NULL, NULL, + DEFAULT_PROTO "mariadb.org/feedback_plugin/post"); +static MYSQL_SYSVAR_ULONG(send_timeout, send_timeout, PLUGIN_VAR_RQCMDARG, + "Timeout (in seconds) for the sending the report.", + NULL, NULL, 60, 1, 60*60*24, 1); +static MYSQL_SYSVAR_ULONG(send_retry_wait, send_retry_wait, PLUGIN_VAR_RQCMDARG, + "Wait this many seconds before retrying a failed send.", + NULL, NULL, 60, 1, 60*60*24, 1); + +static struct st_mysql_sys_var* settings[] = { + MYSQL_SYSVAR(server_uid), + MYSQL_SYSVAR(user_info), + MYSQL_SYSVAR(url), + MYSQL_SYSVAR(send_timeout), + MYSQL_SYSVAR(send_retry_wait), + NULL +}; + + +static struct st_mysql_information_schema feedback = +{ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION }; + +} // namespace feedback + +mysql_declare_plugin(feedback) +{ + MYSQL_INFORMATION_SCHEMA_PLUGIN, + &feedback::feedback, + "FEEDBACK", + "Sergei Golubchik", + "MariaDB User Feedback Plugin", + PLUGIN_LICENSE_GPL, + feedback::init, + feedback::free, + 0x0100, + NULL, + feedback::settings, + NULL +} +mysql_declare_plugin_end; + diff --git a/plugin/feedback/feedback.h b/plugin/feedback/feedback.h new file mode 100644 index 00000000000..60ef72eed84 --- /dev/null +++ b/plugin/feedback/feedback.h @@ -0,0 +1,67 @@ +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#define MYSQL_SERVER +#include <mysql_priv.h> + +namespace feedback { + +int fill_feedback(THD *thd, TABLE_LIST *tables, COND *cond); +int fill_plugin_version(THD *thd, TABLE_LIST *tables); +int fill_misc_data(THD *thd, TABLE_LIST *tables); +int fill_linux_info(THD *thd, TABLE_LIST *tables); + +static const int SERVER_UID_SIZE= 29; +extern char server_uid_buf[SERVER_UID_SIZE+1], *user_info; +int calculate_server_uid(char *); +int prepare_linux_info(); + +extern ST_SCHEMA_TABLE *i_s_feedback; + +extern ulong send_timeout, send_retry_wait; + +pthread_handler_t background_thread(void *arg); + +/** + The class for storing urls to send report data to. + + Constructors are private, the object should be created with create() method. + send() method does the actual sending. +*/ +class Url { + protected: + Url(LEX_STRING &url_arg) : full_url(url_arg) {} + const LEX_STRING full_url; + + public: + virtual ~Url() { my_free(full_url.str, MYF(0)); } + + const char *url() { return full_url.str; } + size_t url_length() { return full_url.length; } + virtual int send(const char* data, size_t data_length) = 0; + + static Url* create(const char *url, size_t url_length); +}; + +extern Url **urls; +extern uint url_count; + +/* these are used to communicate with the background thread */ +extern pthread_mutex_t sleep_mutex; +extern pthread_cond_t sleep_condition; +extern volatile bool shutdown_plugin; + +} // namespace feedback + diff --git a/plugin/feedback/plug.in b/plugin/feedback/plug.in new file mode 100644 index 00000000000..88a4448321d --- /dev/null +++ b/plugin/feedback/plug.in @@ -0,0 +1,28 @@ +MYSQL_PLUGIN(feedback,[MariaDB User Feedback Plugin], + [MariaDB User Feedback Plugin]) + +dnl Although it's not exactly obvious, top-level CMakeLists.txt parses plug.in +dnl files, in particular looking for what the library name should be. It uses +dnl regexp that matches MYSQL_PLUGIN_DYNAMIC or MYSQL_PLUGIN_STATIC, followed +dnl by an open parenthesys, and the plugin name. Having engine name enclosed in +dnl square brackets below causes this regexp to fail and as a result feedback +dnl plugin will not be considered for dynamic builds on Windows. +dnl Unfortunately, feedback cannot be built dynamically on Windows, because it +dnl needs to access server internals that aren't designed for plugin use and +dnl aren't marked with MYSQL_PLUGIN_IMPORT. +MYSQL_PLUGIN_DYNAMIC([feedback], [feedback.la]) +ifelse(index(AC_PACKAGE_NAME, [MariaDB]), -1, [], [ + +dnl MariaDB and MySQL define static plugins differently. +dnl I only support MariaDB here, for now. +MYSQL_PLUGIN_STATIC(feedback, [libfeedback.la]) + +]) + +dnl MariaDB before 5.5 needs this define: +MYSQL_PLUGIN_DEFINE(feedback, [WITH_FEEDBACK_PLUGIN]) + +MYSQL_PLUGIN_ACTIONS(feedback, [ + AC_CHECK_HEADERS([netdb.h sys/utsname.h]) +]) + diff --git a/plugin/feedback/sender_thread.cc b/plugin/feedback/sender_thread.cc new file mode 100644 index 00000000000..617ca0213dc --- /dev/null +++ b/plugin/feedback/sender_thread.cc @@ -0,0 +1,301 @@ +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "feedback.h" +#include <time.h> + +namespace feedback { + +static THD *thd= 0; ///< background thread thd +static my_thread_id thd_thread_id; ///< its thread_id + +static size_t needed_size= 20480; + +static const time_t startup_interval= 60*5; ///< in seconds (5 minutes) +static const time_t first_interval= 60*60*24; ///< in seconds (one day) +static const time_t interval= 60*60*24*7; ///< in seconds (one week) + +/** + reads the rows from a table and puts them, concatenated, in a String + + @note + 1. only supports two column tables - no less, no more. + 2. it emulates mysql -e "select * from..." and thus it separates + columns with \t and starts the output with column names. +*/ +static int table_to_string(TABLE *table, String *result) +{ + bool res; + char buff1[MAX_FIELD_WIDTH], buff2[MAX_FIELD_WIDTH]; + String str1(buff1, sizeof(buff1), system_charset_info); + String str2(buff2, sizeof(buff2), system_charset_info); + + res= table->file->ha_rnd_init(1); + + dbug_tmp_use_all_columns(table, table->read_set); + + while(!res && !table->file->ha_rnd_next(table->record[0])) + { + table->field[0]->val_str(&str1); + table->field[1]->val_str(&str2); + if (result->reserve(str1.length() + str2.length() + 3)) + res= 1; + else + { + result->qs_append(str1.ptr(), str1.length()); + result->qs_append('\t'); + result->qs_append(str2.ptr(), str2.length()); + result->qs_append('\n'); + } + } + + res = res || result->append('\n'); + + /* + Note, "|=" and not "||" - because we want to call ha_rnd_end() + even if res is already 1. + */ + res |= table->file->ha_rnd_end(); + + return res; +} + +/** + Initialize the THD and TABLE_LIST + + The structures must be sufficiently initialized for create_tmp_table() + and fill_feedback() to work. +*/ +static int prepare_for_fill(TABLE_LIST *tables) +{ + /* + Add our thd to the list, for it to be visible in SHOW PROCESSLIST. + But don't generate thread_id every time - use the saved value + (every increment of global thread_id counts as a new connection + in SHOW STATUS and we want to avoid skewing the statistics) + */ + thd->thread_id= thd->variables.pseudo_thread_id= thd_thread_id; + pthread_mutex_lock(&LOCK_thread_count); + thread_count++; + threads.append(thd); + pthread_mutex_unlock(&LOCK_thread_count); + thd->thread_stack= (char*) &tables; + if (thd->store_globals()) + return 1; + + thd->mysys_var->current_cond= &sleep_condition; + thd->mysys_var->current_mutex= &sleep_mutex; + thd->proc_info="feedback"; + thd->command=COM_SLEEP; + thd->version=refresh_version; + thd->system_thread= SYSTEM_THREAD_EVENT_WORKER; // whatever + thd->set_time(); + thd->init_for_queries(); + thd->real_id= pthread_self(); + thd->db= NULL; + thd->db_length= 0; + thd->security_ctx->host_or_ip= ""; + thd->security_ctx->db_access= DB_ACLS; + thd->security_ctx->master_access= ~NO_ACCESS; + bzero((char*) &thd->net, sizeof(thd->net)); + lex_start(thd); + mysql_init_select(thd->lex); + + tables->init_one_table(INFORMATION_SCHEMA_NAME.str, + i_s_feedback->table_name, TL_READ); + tables->schema_table= i_s_feedback; + tables->table= i_s_feedback->create_table(thd, tables); + if (!tables->table) + return 1; + + tables->table->pos_in_table_list= tables; + + return 0; +} + +/** + Try to detect if this thread is going down + + which can happen for different reasons: + * plugin is being unloaded + * mysqld server is being shut down + * the thread is being killed + +*/ +static bool going_down() +{ + return shutdown_plugin || shutdown_in_progress || (thd && thd->killed); +} + +/** + just like sleep, but waits on a condition and checks "plugin shutdown" status +*/ +static int slept_ok(time_t sec) +{ + struct timespec abstime; + int ret= 0; + + set_timespec(abstime, sec); + + pthread_mutex_lock(&sleep_mutex); + while (!going_down() && ret != ETIMEDOUT) + ret= pthread_cond_timedwait(&sleep_condition, &sleep_mutex, &abstime); + pthread_mutex_unlock(&sleep_mutex); + + return !going_down(); +} + +/** + create a feedback report and send it to all specified urls + + If "when" argument is not null, only it and the server uid are sent. + Otherwise a full report is generated. +*/ +static void send_report(const char *when) +{ + TABLE_LIST tables; + String str; + int i, last_todo; + Url **todo= (Url**)alloca(url_count*sizeof(Url*)); + + str.alloc(needed_size); // preallocate it to avoid many small mallocs + + /* + on startup and shutdown the server may not be completely + initialized, and full report won't work. + We send a short status notice only. + */ + if (when) + { + str.length(0); + str.append(STRING_WITH_LEN("FEEDBACK_SERVER_UID")); + str.append('\t'); + str.append(server_uid_buf); + str.append('\n'); + str.append(STRING_WITH_LEN("FEEDBACK_WHEN")); + str.append('\t'); + str.append(when); + str.append('\n'); + str.append(STRING_WITH_LEN("FEEDBACK_USER_INFO")); + str.append('\t'); + str.append(user_info); + str.append('\n'); + str.append('\n'); + } + else + { + /* + otherwise, prepare the THD and TABLE_LIST, + create and fill the temporary table with data just like + SELECT * FROM IFROEMATION_SCHEMA.feedback is doing, + read and concatenate table data into a String. + */ + if (!(thd= new THD())) + return; + + if (prepare_for_fill(&tables)) + goto ret; + + if (fill_feedback(thd, &tables, NULL)) + goto ret; + + if (table_to_string(tables.table, &str)) + goto ret; + + needed_size= (size_t)(str.length() * 1.1); + + free_tmp_table(thd, tables.table); + tables.table= 0; + } + + /* + Try to send the report on every url from the list, remove url on success, + keep failed in the list. Repeat until the list is empty. + */ + memcpy(todo, urls, url_count*sizeof(Url*)); + last_todo= url_count - 1; + do + { + for (i= 0; i <= last_todo;) + { + Url *url= todo[i]; + + if (thd) // for nicer SHOW PROCESSLIST + thd->set_query(const_cast<char*>(url->url()), url->url_length()); + + if (url->send(str.ptr(), str.length())) + i++; + else + todo[i]= todo[last_todo--]; + } + if (last_todo < 0) + break; + } while (slept_ok(send_retry_wait)); // wait a little bit before retrying + +ret: + if (thd) + { + if (tables.table) + free_tmp_table(thd, tables.table); + /* + clean up, free the thd. + reset all thread local status variables to minimize + the effect of the background thread on SHOW STATUS. + */ + pthread_mutex_lock(&LOCK_thread_count); + bzero(&thd->status_var, sizeof(thd->status_var)); + thread_count--; + thd->killed= THD::KILL_CONNECTION; + pthread_cond_broadcast(&COND_thread_count); + pthread_mutex_unlock(&LOCK_thread_count); + delete thd; + thd= 0; + } +} + +/** + background sending thread +*/ +pthread_handler_t background_thread(void *arg __attribute__((unused))) +{ + if (my_thread_init()) + return 0; + + pthread_mutex_lock(&LOCK_thread_count); + thd_thread_id= thread_id++; + pthread_mutex_unlock(&LOCK_thread_count); + + if (slept_ok(startup_interval)) + { + send_report("startup"); + + if (slept_ok(first_interval)) + { + send_report(NULL); + + while(slept_ok(interval)) + send_report(NULL); + } + + send_report("shutdown"); + } + + my_thread_end(); + pthread_exit(0); + return 0; +} + +} // namespace feedback + diff --git a/plugin/feedback/url_base.cc b/plugin/feedback/url_base.cc new file mode 100644 index 00000000000..38b2ca86e9f --- /dev/null +++ b/plugin/feedback/url_base.cc @@ -0,0 +1,51 @@ +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "feedback.h" + +namespace feedback { + +Url* http_create(const char *url, size_t url_length); + +/** + creates an Url object out of an url, if possible. + + This is done by invoking corresponding creator functions + of the derived classes, until the first not NULL result. +*/ +Url* Url::create(const char *url, size_t url_length) +{ + url= my_strndup(url, url_length, MYF(MY_WME)); + + if (!url) + return NULL; + + Url *self= http_create(url, url_length); + + /* + here we can add + + if (!self) self= smtp_create(url, url_length); + if (!self) self= tftp_create(url, url_length); + etc + */ + + if (!self) + my_free(const_cast<char*>(url), MYF(0)); + + return self; +} + +} // namespace feedback diff --git a/plugin/feedback/url_http.cc b/plugin/feedback/url_http.cc new file mode 100644 index 00000000000..de2877b0274 --- /dev/null +++ b/plugin/feedback/url_http.cc @@ -0,0 +1,303 @@ +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "feedback.h" + +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif + +#ifdef _WIN32 +#undef VOID +#define VOID void +#include <ws2tcpip.h> +#define addrinfo ADDRINFOA +#endif + +namespace feedback { + +static const uint FOR_READING= 0; +static const uint FOR_WRITING= 1; + +#ifdef MARIADB_BASE_VERSION +#define ssl_connect(A,B,C,D) sslconnect(A,B,C,D) +#else +#define ssl_connect(A,B,C,D) sslconnect(A,B,C) +#endif + +/** + implementation of the Url class that sends the data via HTTP POST request. + + Both http:// and https:// protocols are supported. +*/ +class Url_http: public Url { + protected: + const LEX_STRING host, port, path; + bool ssl; + + Url_http(LEX_STRING &url_arg, LEX_STRING &host_arg, + LEX_STRING &port_arg, LEX_STRING &path_arg, bool ssl_arg) : + Url(url_arg), host(host_arg), port(port_arg), path(path_arg), ssl(ssl_arg) + {} + ~Url_http() + { + my_free(host.str, MYF(0)); + my_free(port.str, MYF(0)); + my_free(path.str, MYF(0)); + } + + public: + int send(const char* data, size_t data_length); + + friend Url* http_create(const char *url, size_t url_length); +}; + +/** + create a Url_http object out of the url, if possible. + + @note + Arbitrary limitations here. + + The url must be http[s]://hostname[:port]/path + No username:password@ or ?script=parameters are supported. + + But it's ok. This is not a generic purpose www browser - it only needs to be + good enough to POST the data to mariadb.org. +*/ +Url* http_create(const char *url, size_t url_length) +{ + const char *s; + LEX_STRING full_url= {const_cast<char*>(url), url_length}; + LEX_STRING host, port, path; + bool ssl= false; + + if (is_prefix(url, "http://")) + s= url + 7; +#ifdef HAVE_OPENSSL + else if (is_prefix(url, "https://")) + { + ssl= true; + s= url + 8; + } +#endif + else + return NULL; + + for (url= s; *s && *s != ':' && *s != '/'; s++) /* no-op */; + host.str= const_cast<char*>(url); + host.length= s-url; + + if (*s == ':') + { + for (url= ++s; *s && *s >= '0' && *s <= '9'; s++) /* no-op */; + port.str= const_cast<char*>(url); + port.length= s-url; + } + else + { + if (ssl) + { + port.str= const_cast<char*>("443"); + port.length=3; + } + else + { + port.str= const_cast<char*>("80"); + port.length=2; + } + } + + if (*s == 0) + { + path.str= const_cast<char*>("/"); + path.length= 1; + } + else + { + path.str= const_cast<char*>(s); + path.length= strlen(s); + } + if (!host.length || !port.length || path.str[0] != '/') + return NULL; + + host.str= my_strndup(host.str, host.length, MYF(MY_WME)); + port.str= my_strndup(port.str, port.length, MYF(MY_WME)); + path.str= my_strndup(path.str, path.length, MYF(MY_WME)); + + if (!host.str || !port.str || !path.str) + { + my_free(host.str, MYF(MY_ALLOW_ZERO_PTR)); + my_free(port.str, MYF(MY_ALLOW_ZERO_PTR)); + my_free(path.str, MYF(MY_ALLOW_ZERO_PTR)); + return NULL; + } + + return new Url_http(full_url, host, port, path, ssl); +} + +/* do the vio_write and check that all data were sent ok */ +#define write_check(VIO, DATA, LEN) \ + (vio_write((VIO), (uchar*)(DATA), (LEN)) != (LEN)) + +int Url_http::send(const char* data, size_t data_length) +{ + my_socket fd= INVALID_SOCKET; + char buf[1024]; + uint len; + + addrinfo *addrs, *addr, filter= {0, AF_UNSPEC, SOCK_STREAM, 6, 0, 0, 0, 0}; + int res= getaddrinfo(host.str, port.str, &filter, &addrs); + + if (res) + { + sql_print_error("feedback plugin: getaddrinfo() failed for url '%s': %s", + full_url.str, gai_strerror(res)); + return 1; + } + + for (addr= addrs; addr != NULL; addr= addr->ai_next) + { + fd= socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); + if (fd == INVALID_SOCKET) + continue; + + if (connect(fd, addr->ai_addr, addr->ai_addrlen) == 0) + break; + + closesocket(fd); + } + + freeaddrinfo(addrs); + + if (fd == INVALID_SOCKET) + { + sql_print_error("feedback plugin: could not connect for url '%s'", + full_url.str); + return 1; + } + + Vio *vio= vio_new(fd, VIO_TYPE_TCPIP, 0); + if (!vio) + { + sql_print_error("feedback plugin: vio_new failed for url '%s'", + full_url.str); + closesocket(fd); + return 1; + } + +#ifdef HAVE_OPENSSL + struct st_VioSSLFd *ssl_fd; + if (ssl) + { + buf[0]= 0; + if (!(ssl_fd= new_VioSSLConnectorFd(0, 0, 0, 0, 0)) || + ssl_connect(ssl_fd, vio, send_timeout, buf)) + { + sql_print_error("feedback plugin: ssl failed for url '%s' %s", + full_url.str, buf); + if (ssl_fd) + free_vio_ssl_acceptor_fd(ssl_fd); + closesocket(fd); + vio_delete(vio); + return 1; + } + } +#endif + + static const LEX_STRING boundary= + { C_STRING_WITH_LEN("----------------------------ba4f3696b39f") }; + static const LEX_STRING header= + { C_STRING_WITH_LEN("\r\n" + "Content-Disposition: form-data; name=\"data\"; filename=\"-\"\r\n" + "Content-Type: application/octet-stream\r\n\r\n") + }; + + len= my_snprintf(buf, sizeof(buf), + "POST %s HTTP/1.0\r\n" + "User-Agent: MariaDB User Feedback Plugin\r\n" + "Host: %s:%s\r\n" + "Accept: */*\r\n" + "Content-Length: %u\r\n" + "Content-Type: multipart/form-data; boundary=%s\r\n" + "\r\n", + path.str, host.str, port.str, + (uint)(2*boundary.length + header.length + data_length + 4), + boundary.str + 2); + + vio_timeout(vio, FOR_READING, send_timeout); + vio_timeout(vio, FOR_WRITING, send_timeout); + res = write_check(vio, buf, len) + || write_check(vio, boundary.str, boundary.length) + || write_check(vio, header.str, header.length) + || write_check(vio, data, data_length) + || write_check(vio, boundary.str, boundary.length) + || write_check(vio, "--\r\n", 4); + + if (res) + sql_print_error("feedback plugin: failed to send report to '%s'", + full_url.str); + else + { + sql_print_information("feedback plugin: report to '%s' was sent", + full_url.str); + + /* + if the data were send successfully, read the reply. + Extract the first string between <h1>...</h1> tags + and put it as a server reply into the error log. + */ + len= vio_read(vio, (uchar*)buf, sizeof(buf)-1); + if (len && len < sizeof(buf)) + { + char *from; + + buf[len+1]= 0; // safety + + if ((from= strstr(buf, "<h1>"))) + { + from+= 4; + char *to= strstr(from, "</h1>"); + if (to) + *to= 0; + else + from= NULL; + } + if (from) + sql_print_information("feedback plugin: server replied '%s'", from); + else + sql_print_warning("feedback plugin: failed to parse server reply"); + } + else + { + res= 1; + sql_print_error("feedback plugin: failed to read server reply"); + } + } + + vio_delete(vio); + +#ifdef HAVE_OPENSSL + if (ssl) + { + SSL_CTX_free(ssl_fd->ssl_context); + my_free(ssl_fd, MYF(0)); + } +#endif + + return res; +} + +} // namespace feedback + diff --git a/plugin/feedback/utils.cc b/plugin/feedback/utils.cc new file mode 100644 index 00000000000..db19e9ae9b4 --- /dev/null +++ b/plugin/feedback/utils.cc @@ -0,0 +1,387 @@ +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "feedback.h" + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + +#include <base64.h> +#include <sha1.h> + +#if defined (_WIN32) +#define HAVE_SYS_UTSNAME_H +struct utsname { + char sysname[16]; // Name of this implementation of the operating system. + char nodename[16]; // Name of this node within the communications + // network to which this node is attached, if any. + char release[16]; // Current release level of this implementation. + char version[256]; // Current version level of this release. + char machine[16]; // Name of the hardware type on which the system is running. +}; + +/* Get commonly used name for Windows version */ +static const char *get_os_version_name(OSVERSIONINFOEX *ver) +{ + DWORD major = ver->dwMajorVersion; + DWORD minor = ver->dwMinorVersion; + + if (major == 6 && minor == 1) + { + return (ver->wProductType == VER_NT_WORKSTATION)? + "Windows 7":"Windows Server 2008 R2"; + } + if (major == 6 && minor == 0) + { + return (ver->wProductType == VER_NT_WORKSTATION)? + "Windows Vista":"Windows Server 2008"; + } + if (major == 5 && minor == 2) + { + if (GetSystemMetrics(SM_SERVERR2) != 0) + return "Windows Server 2003 R2"; + if (ver->wSuiteMask & VER_SUITE_WH_SERVER) + return "Windows Home Server"; + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + if (ver->wProductType == VER_NT_WORKSTATION && + sysinfo.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_AMD64) + return "Windows XP Professional x64 Edition"; + + return "Windows Server 2003"; + } + if (major == 5 && minor == 1) + return "Windows XP"; + if (major == 5 && minor == 0) + return "Windows 2000"; + + return ""; +} + + +static int uname(struct utsname *buf) +{ + OSVERSIONINFOEX ver; + ver.dwOSVersionInfoSize = (DWORD)sizeof(ver); + if (!GetVersionEx((OSVERSIONINFO *)&ver)) + return -1; + + buf->nodename[0]= 0; + strcpy(buf->sysname, "Windows"); + sprintf(buf->release, "%d.%d", ver.dwMajorVersion, ver.dwMinorVersion); + + const char *version_str= get_os_version_name(&ver); + if(version_str && version_str[0]) + sprintf(buf->version, "%s %s",version_str, ver.szCSDVersion); + else + sprintf(buf->version, "%s", ver.szCSDVersion); + +#ifdef _WIN64 + strcpy(buf->machine, "x64"); +#else + BOOL isX64; + if (IsWow64Process(GetCurrentProcess(), &isX64) && isX64) + strcpy(buf->machine, "x64"); + else + strcpy(buf->machine,"x86"); +#endif + return 0; +} + +#elif defined(HAVE_SYS_UTSNAME_H) +#include <sys/utsname.h> +#endif + +#ifdef HAVE_SYS_UTSNAME_H +static bool have_ubuf= false; +static struct utsname ubuf; +#endif + +#ifdef TARGET_OS_LINUX +#include <glob.h> +static bool have_distribution= false; +static char distribution[256]; + +static const char *masks[]= { + "/etc/*-version", "/etc/*-release", + "/etc/*_version", "/etc/*_release" +}; +#endif + +bool schema_table_store_record(THD *thd, TABLE *table); + +namespace feedback { + +/* + convenience macros for inserting rows into I_S table. +*/ +#define INSERT2(NAME,LEN,VALUE) \ + do { \ + table->field[0]->store(NAME, LEN, system_charset_info); \ + table->field[1]->store VALUE; \ + if (schema_table_store_record(thd, table)) \ + return 1; \ + } while (0) + +#define INSERT1(NAME,VALUE) \ + do { \ + table->field[0]->store(NAME, sizeof(NAME)-1, system_charset_info); \ + table->field[1]->store VALUE; \ + if (schema_table_store_record(thd, table)) \ + return 1; \ + } while (0) + +static const bool UNSIGNED= true; ///< used below when inserting integers + +/** + callback for fill_plugin_version() - insert a plugin name and its version +*/ +static my_bool show_plugins(THD *thd, plugin_ref plugin, void *arg) +{ + TABLE *table= (TABLE*) arg; + char version[20]; + size_t version_len; + + version_len= my_snprintf(version, sizeof(version), "%d.%d", + (plugin_decl(plugin)->version) >> 8, + (plugin_decl(plugin)->version) & 0xff); + + INSERT2(plugin_name(plugin)->str, plugin_name(plugin)->length, + (version, version_len, system_charset_info)); + + return 0; +} + +/** + inserts all plugins and their versions into I_S.FEEDBACK +*/ +int fill_plugin_version(THD *thd, TABLE_LIST *tables) +{ + return plugin_foreach_with_mask(thd, show_plugins, MYSQL_ANY_PLUGIN, + ~PLUGIN_IS_FREED, tables->table); +} + +#if defined(_SC_PAGE_SIZE) && !defined(_SC_PAGESIZE) +#define _SC_PAGESIZE _SC_PAGE_SIZE +#endif + +/** + return the amount of physical memory +*/ +static ulonglong my_getphysmem() +{ + ulonglong pages= 0; +#ifdef _SC_PHYS_PAGES + pages= sysconf(_SC_PHYS_PAGES); +#else + return 0; +#endif + +#ifdef _SC_PAGESIZE + return pages * sysconf(_SC_PAGESIZE); +#endif +#ifdef _WIN32 + MEMORYSTATUSEX memstatus; + memstatus.dwLength= sizeof(memstatus); + GlobalMemoryStatusEx(&memstatus); + return memstatus.ullTotalPhys; +#else + return pages * my_getpagesize(); +#endif +} + +/* get the number of (online) CPUs */ +int my_getncpus() +{ +#ifdef _SC_NPROCESSORS_ONLN + return sysconf(_SC_NPROCESSORS_ONLN); +#elif defined(__WIN__) + SYSTEM_INFO sysinfo; + GetSystemInfo(&sysinfo); + return sysinfo.dwNumberOfProcessors; +#else + return 0; +#endif +} + +/** + Find the version of the kernel and the linux distribution +*/ +int prepare_linux_info() +{ +#ifdef HAVE_SYS_UTSNAME_H + have_ubuf= (uname(&ubuf) != -1); +#endif + +#ifdef TARGET_OS_LINUX + /* + let's try to find what linux distribution it is + we read *[-_]{release,version} file in /etc. + + Either it will be /etc/lsb-release, such as + + ==> /etc/lsb-release <== + DISTRIB_ID=Ubuntu + DISTRIB_RELEASE=8.04 + DISTRIB_CODENAME=hardy + DISTRIB_DESCRIPTION="Ubuntu 8.04.4 LTS" + + Or a one-liner with the description (/etc/SuSE-release has more + than one line, but the description is the first, so it can be + treated as a one-liner). + + We'll read lsb-release first, and if it's not found will search + for other files (*-version *-release *_version *_release) +*/ + int fd; + have_distribution= false; + if ((fd= my_open("/etc/lsb-release", O_RDONLY, MYF(0))) != -1) + { + /* Cool, LSB-compliant distribution! */ + size_t len= my_read(fd, (uchar*)distribution, sizeof(distribution)-1, MYF(0)); + my_close(fd, MYF(0)); + if (len != (size_t)-1) + { + distribution[len]= 0; // safety + char *found= strstr(distribution, "DISTRIB_DESCRIPTION="); + if (found) + { + have_distribution= true; + char *end= strstr(found, "\n"); + if (end == NULL) + end= distribution + len; + found+= 20; + + if (*found == '"' && end[-1] == '"') + { + found++; + end--; + } + *end= 0; + + char *to= strmov(distribution, "lsb: "); + memmove(to, found, end - found + 1); + } + } + } + + /* if not an LSB-compliant distribution */ + for (uint i= 0; !have_distribution && i < array_elements(masks); i++) + { + glob_t found; + if (glob(masks[i], GLOB_NOSORT, NULL, &found) == 0) + { + int fd; + if ((fd= my_open(found.gl_pathv[0], O_RDONLY, MYF(0))) != -1) + { + /* + +5 and -8 below cut the file name part out of the + full pathname that corresponds to the mask as above. + */ + char *to= strmov(distribution, found.gl_pathv[0] + 5) - 8; + *to++= ':'; + *to++= ' '; + + size_t to_len= distribution + sizeof(distribution) - 1 - to; + size_t len= my_read(fd, (uchar*)to, to_len, MYF(0)); + my_close(fd, MYF(0)); + if (len != (size_t)-1) + { + to[len]= 0; // safety + char *end= strstr(to, "\n"); + if (end) + *end= 0; + have_distribution= true; + } + } + } + globfree(&found); + } +#endif + return 0; +} + +/** + Add the linux distribution and the kernel version +*/ +int fill_linux_info(THD *thd, TABLE_LIST *tables) +{ + TABLE *table= tables->table; + CHARSET_INFO *cs= system_charset_info; + +#ifdef HAVE_SYS_UTSNAME_H + if (have_ubuf) + { + INSERT1("Uname_sysname", (ubuf.sysname, strlen(ubuf.sysname), cs)); + INSERT1("Uname_release", (ubuf.release, strlen(ubuf.release), cs)); + INSERT1("Uname_version", (ubuf.version, strlen(ubuf.version), cs)); + INSERT1("Uname_machine", (ubuf.machine, strlen(ubuf.machine), cs)); + } +#endif + +#ifdef TARGET_OS_LINUX + if (have_distribution) + INSERT1("Uname_distribution", (distribution, strlen(distribution), cs)); +#endif + + return 0; +} + +/** + Adds varios bits of information to the I_S.FEEDBACK +*/ +int fill_misc_data(THD *thd, TABLE_LIST *tables) +{ + TABLE *table= tables->table; + +#ifdef MY_ATOMIC_OK + INSERT1("Cpu_count", (my_getncpus(), UNSIGNED)); +#endif + INSERT1("Mem_total", (my_getphysmem(), UNSIGNED)); + + return 0; +} + +/** + calculates the server unique identifier + + UID is a base64 encoded SHA1 hash of the MAC address of one of + the interfaces, and the tcp port that the server is listening on +*/ +int calculate_server_uid(char *dest) +{ + uchar rawbuf[2 + 6]; + uchar shabuf[SHA1_HASH_SIZE]; + SHA1_CONTEXT ctx; + + int2store(rawbuf, mysqld_port); + if (my_gethwaddr(rawbuf + 2)) + { + sql_print_error("feedback plugin: failed to retrieve the MAC address"); + return 1; + } + + mysql_sha1_reset(&ctx); + mysql_sha1_input(&ctx, rawbuf, sizeof(rawbuf)); + mysql_sha1_result(&ctx, shabuf); + + assert(base64_needed_encoded_length(sizeof(shabuf)) <= SERVER_UID_SIZE); + base64_encode(shabuf, sizeof(shabuf), dest); + + return 0; +} + +} // namespace feedback diff --git a/plugin/fulltext/CMakeLists.txt b/plugin/fulltext/CMakeLists.txt new file mode 100644 index 00000000000..cf696c19e61 --- /dev/null +++ b/plugin/fulltext/CMakeLists.txt @@ -0,0 +1,3 @@ +INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake") +SET(FTEXAMPLE_SOURCES plugin_example.c) +MYSQL_PLUGIN(FTEXAMPLE) diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index cf60b888229..03211b1b18e 100755 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -37,7 +37,9 @@ SET_SOURCE_FILES_PROPERTIES(${CMAKE_BINARY_DIR}/sql/sql_yacc.h PROPERTIES GENERATED 1) ADD_DEFINITIONS(-DMYSQL_SERVER -D_CONSOLE -DHAVE_DLOPEN -DHAVE_EVENT_SCHEDULER) - +IF(WITH_FEEDBACK_STORAGE_ENGINE) + ADD_DEFINITIONS(-DWITH_FEEDBACK_PLUGIN) +ENDIF() SET (SQL_SOURCE ../sql-common/client.c derror.cc des_key_file.cc diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index 264901f505e..7bcef85020c 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -3381,6 +3381,19 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp, opt->name, plugin_name); } } + /* + PLUGIN_VAR_STR command-line options without PLUGIN_VAR_MEMALLOC, point + directly to values in the argv[] array. For plugins started at the + server startup, argv[] array is allocated with load_defaults(), and + freed when the server is shut down. But for plugins loaded with + INSTALL PLUGIN, the memory allocated with load_defaults() is freed with + freed() at the end of mysql_install_plugin(). Which means we cannot + allow any pointers into that area. + Thus, for all plugins loaded after the server was started, + we force all command-line options to be PLUGIN_VAR_MEMALLOC + */ + if (mysqld_server_started && !(opt->flags & PLUGIN_VAR_NOCMDOPT)) + opt->flags|= PLUGIN_VAR_MEMALLOC; break; case PLUGIN_VAR_ENUM: if (!opt->check) @@ -3537,6 +3550,10 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp, if (!my_strcasecmp(&my_charset_latin1, tmp->name.str, "ndbcluster")) plugin_load_policy= PLUGIN_OFF; #endif +#ifdef WITH_FEEDBACK_PLUGIN + if (!my_strcasecmp(&my_charset_latin1, tmp->name.str, "feedback")) + plugin_load_policy= PLUGIN_OFF; +#endif for (opt= tmp->plugin->system_vars; opt && *opt; opt++) count+= 2; /* --{plugin}-{optname} and --plugin-{plugin}-{optname} */ diff --git a/storage/blackhole/plug.in b/storage/blackhole/plug.in index 2f3b120fa5d..84b7299969b 100644 --- a/storage/blackhole/plug.in +++ b/storage/blackhole/plug.in @@ -1,6 +1,5 @@ MYSQL_STORAGE_ENGINE(blackhole,,[Blackhole Storage Engine], [Basic Write-only Read-never tables], [max,max-no-ndb]) -MYSQL_PLUGIN_DIRECTORY(blackhole, [storage/blackhole]) MYSQL_PLUGIN_STATIC(blackhole, [libblackhole.la]) MYSQL_PLUGIN_DYNAMIC(blackhole, [ha_blackhole.la]) diff --git a/storage/csv/plug.in b/storage/csv/plug.in index 4ff32959fa2..eb4bd4d9883 100644 --- a/storage/csv/plug.in +++ b/storage/csv/plug.in @@ -1,5 +1,4 @@ MYSQL_STORAGE_ENGINE(csv,, [CSV Storage Engine], [Stores tables in text CSV format]) -MYSQL_PLUGIN_DIRECTORY(csv, [storage/csv]) MYSQL_PLUGIN_STATIC(csv, [libcsv.la]) MYSQL_PLUGIN_MANDATORY(csv) dnl Used for logging diff --git a/storage/heap/plug.in b/storage/heap/plug.in index 92ec01d3c88..f1b02b38c2b 100644 --- a/storage/heap/plug.in +++ b/storage/heap/plug.in @@ -1,6 +1,5 @@ MYSQL_STORAGE_ENGINE(heap,no, [Memory Storage Engine], [Volatile memory based tables]) -MYSQL_PLUGIN_DIRECTORY(heap, [storage/heap]) MYSQL_PLUGIN_STATIC(heap, [libheap_s.la], [libheap_embedded.la]) MYSQL_PLUGIN_MANDATORY(heap) dnl Memory tables diff --git a/storage/innobase/plug.in.disabled b/storage/innobase/plug.in.disabled index b18950b9c7a..2d6af1d2883 100644 --- a/storage/innobase/plug.in.disabled +++ b/storage/innobase/plug.in.disabled @@ -1,6 +1,5 @@ MYSQL_STORAGE_ENGINE(innobase, innodb, [InnoDB Storage Engine], [Transactional Tables using InnoDB], [max,max-no-ndb]) -MYSQL_PLUGIN_DIRECTORY(innobase, [storage/innobase]) MYSQL_PLUGIN_STATIC(innobase, [libinnobase.la]) MYSQL_PLUGIN_DYNAMIC(innobase, [ha_innodb.la]) MYSQL_PLUGIN_ACTIONS(innobase, [ diff --git a/storage/innodb_plugin/plug.in b/storage/innodb_plugin/plug.in index ebaa3f574a0..e5e2def5435 100644 --- a/storage/innodb_plugin/plug.in +++ b/storage/innodb_plugin/plug.in @@ -16,7 +16,6 @@ MYSQL_STORAGE_ENGINE(innodb_plugin,, [InnoDB Storage Engine], [Transactional Tables using InnoDB], []) -MYSQL_PLUGIN_DIRECTORY(innodb_plugin, [storage/innodb_plugin]) # Enable if you know what you are doing (trying to link both InnoDB and # InnoDB Plugin statically into MySQL does not work). #MYSQL_PLUGIN_STATIC(innodb_plugin, [libinnobase.a]) diff --git a/storage/maria/CMakeLists.txt b/storage/maria/CMakeLists.txt index 6ffc8d992b4..82a631d5086 100644 --- a/storage/maria/CMakeLists.txt +++ b/storage/maria/CMakeLists.txt @@ -49,36 +49,36 @@ MYSQL_STORAGE_ENGINE(ARIA) IF(NOT SOURCE_SUBLIBS) - ADD_DEPENDENCIES(aria GenError) + ADD_DEPENDENCIES(libaria_s GenError) MYSQL_ADD_EXECUTABLE(aria_ftdump maria_ftdump.c) -TARGET_LINK_LIBRARIES(aria_ftdump aria myisam mysys dbug strings zlib wsock32) +TARGET_LINK_LIBRARIES(aria_ftdump libaria_s libmyisam_s mysys dbug strings zlib wsock32) MYSQL_ADD_EXECUTABLE(aria_chk maria_chk.c) -TARGET_LINK_LIBRARIES(aria_chk aria myisam mysys dbug strings zlib wsock32) +TARGET_LINK_LIBRARIES(aria_chk libaria_s libmyisam_s mysys dbug strings zlib wsock32) MYSQL_ADD_EXECUTABLE(aria_read_log maria_read_log.c) -TARGET_LINK_LIBRARIES(aria_read_log aria myisam mysys dbug strings zlib wsock32) +TARGET_LINK_LIBRARIES(aria_read_log libaria_s libmyisam_s mysys dbug strings zlib wsock32) MYSQL_ADD_EXECUTABLE(aria_pack maria_pack.c) -TARGET_LINK_LIBRARIES(aria_pack aria myisam mysys dbug strings zlib wsock32) +TARGET_LINK_LIBRARIES(aria_pack libaria_s libmyisam_s mysys dbug strings zlib wsock32) MYSQL_ADD_EXECUTABLE(aria_dump_log maria_dump_log.c unittest/ma_loghandler_examples.c) -TARGET_LINK_LIBRARIES(aria_dump_log aria myisam mysys dbug strings zlib wsock32) +TARGET_LINK_LIBRARIES(aria_dump_log libaria_s libmyisam_s mysys dbug strings zlib wsock32) ADD_EXECUTABLE(ma_test1 ma_test1.c) -TARGET_LINK_LIBRARIES(ma_test1 aria myisam mysys dbug strings zlib wsock32) +TARGET_LINK_LIBRARIES(ma_test1 libaria_s libmyisam_s mysys dbug strings zlib wsock32) ADD_EXECUTABLE(ma_test2 ma_test2.c) -TARGET_LINK_LIBRARIES(ma_test2 aria myisam mysys dbug strings zlib wsock32) +TARGET_LINK_LIBRARIES(ma_test2 libaria_s libmyisam_s mysys dbug strings zlib wsock32) ADD_EXECUTABLE(ma_test3 ma_test3.c) -TARGET_LINK_LIBRARIES(ma_test3 aria myisam mysys dbug strings zlib wsock32) +TARGET_LINK_LIBRARIES(ma_test3 libaria_s libmyisam_s mysys dbug strings zlib wsock32) ADD_EXECUTABLE(ma_rt_test ma_rt_test.c) -TARGET_LINK_LIBRARIES(ma_rt_test aria myisam mysys dbug strings zlib wsock32) +TARGET_LINK_LIBRARIES(ma_rt_test libaria_s libmyisam_s mysys dbug strings zlib wsock32) ADD_EXECUTABLE(ma_sp_test ma_sp_test.c) -TARGET_LINK_LIBRARIES(ma_sp_test aria myisam mysys dbug strings zlib wsock32) +TARGET_LINK_LIBRARIES(ma_sp_test libaria_s libmyisam_s mysys dbug strings zlib wsock32) ENDIF(NOT SOURCE_SUBLIBS) diff --git a/storage/maria/plug.in b/storage/maria/plug.in index c48928be44f..609adcb2f66 100644 --- a/storage/maria/plug.in +++ b/storage/maria/plug.in @@ -1,6 +1,5 @@ MYSQL_STORAGE_ENGINE(aria,, [Aria Storage Engine], [Crash-safe tables with MyISAM heritage], [default,max,max-no-ndb]) -MYSQL_PLUGIN_DIRECTORY(aria, [storage/maria]) MYSQL_PLUGIN_STATIC(aria, [libaria_s.la], [libaria_embedded.la]) MYSQL_PLUGIN_ACTIONS(aria, [ diff --git a/storage/maria/unittest/CMakeLists.txt b/storage/maria/unittest/CMakeLists.txt index a6e8736daab..715a6199185 100644 --- a/storage/maria/unittest/CMakeLists.txt +++ b/storage/maria/unittest/CMakeLists.txt @@ -13,10 +13,9 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib ${CMAKE_SOURCE_DIR}/unittest/mytap) -LINK_LIBRARIES(maria myisam mytap mysys dbug strings wsock32 zlib) +LINK_LIBRARIES(libmaria_s libmyisam_s mytap mysys dbug strings wsock32 zlib) ADD_EXECUTABLE(ma_control_file-t ma_control_file-t.c) ADD_EXECUTABLE(trnman-t trnman-t.c) diff --git a/storage/myisam/CMakeLists.txt b/storage/myisam/CMakeLists.txt index e7e3de64cf3..ce27c209418 100644 --- a/storage/myisam/CMakeLists.txt +++ b/storage/myisam/CMakeLists.txt @@ -32,31 +32,31 @@ MYSQL_STORAGE_ENGINE(MYISAM) IF(NOT SOURCE_SUBLIBS) MYSQL_ADD_EXECUTABLE(myisam_ftdump myisam_ftdump.c DESTINATION bin) - TARGET_LINK_LIBRARIES(myisam_ftdump myisam mysys debug dbug strings zlib wsock32) + TARGET_LINK_LIBRARIES(myisam_ftdump libmyisam_s mysys debug dbug strings zlib wsock32) MYSQL_ADD_EXECUTABLE(myisamchk myisamchk.c DESTINATION bin) - TARGET_LINK_LIBRARIES(myisamchk myisam mysys debug dbug strings zlib wsock32) + TARGET_LINK_LIBRARIES(myisamchk libmyisam_s mysys debug dbug strings zlib wsock32) MYSQL_ADD_EXECUTABLE(myisamlog myisamlog.c DESTINATION bin) - TARGET_LINK_LIBRARIES(myisamlog myisam mysys debug dbug strings zlib wsock32) + TARGET_LINK_LIBRARIES(myisamlog libmyisam_s mysys debug dbug strings zlib wsock32) MYSQL_ADD_EXECUTABLE(myisampack myisampack.c DESTINATION bin) - TARGET_LINK_LIBRARIES(myisampack myisam mysys debug dbug strings zlib wsock32) + TARGET_LINK_LIBRARIES(myisampack libmyisam_s mysys debug dbug strings zlib wsock32) ADD_EXECUTABLE(mi_test1 mi_test1.c) - TARGET_LINK_LIBRARIES(mi_test1 myisam mysys debug dbug strings zlib wsock32) + TARGET_LINK_LIBRARIES(mi_test1 libmyisam_s mysys debug dbug strings zlib wsock32) ADD_EXECUTABLE(mi_test2 mi_test2.c) - TARGET_LINK_LIBRARIES(mi_test2 myisam mysys debug dbug strings zlib wsock32) + TARGET_LINK_LIBRARIES(mi_test2 libmyisam_s mysys debug dbug strings zlib wsock32) ADD_EXECUTABLE(mi_test3 mi_test3.c) - TARGET_LINK_LIBRARIES(mi_test3 myisam mysys debug dbug strings zlib wsock32) + TARGET_LINK_LIBRARIES(mi_test3 libmyisam_s mysys debug dbug strings zlib wsock32) ADD_EXECUTABLE(sp_test sp_test.c) - TARGET_LINK_LIBRARIES(sp_test myisam mysys debug dbug strings zlib wsock32) + TARGET_LINK_LIBRARIES(sp_test libmyisam_s mysys debug dbug strings zlib wsock32) ADD_EXECUTABLE(rt_test rt_test.c) - TARGET_LINK_LIBRARIES(rt_test myisam mysys debug dbug strings zlib wsock32) + TARGET_LINK_LIBRARIES(rt_test libmyisam_s mysys debug dbug strings zlib wsock32) SET_TARGET_PROPERTIES(myisamchk myisampack PROPERTIES LINK_FLAGS "setargv.obj") diff --git a/storage/myisam/plug.in b/storage/myisam/plug.in index 95b29336493..0ec7ea1e1d2 100644 --- a/storage/myisam/plug.in +++ b/storage/myisam/plug.in @@ -1,6 +1,5 @@ dnl MYSQL_STORAGE_ENGINE(myisam,no, [MyISAM Storage Engine], dnl [Traditional non-transactional MySQL tables]) -dnl MYSQL_PLUGIN_DIRECTORY(myisam, [storage/myisam]) dnl MYSQL_PLUGIN_STATIC(myisam, [libmyisam_s.la], [libmyisam_embedded.la]) dnl MYSQL_PLUGIN_MANDATORY(myisam) dnl Default diff --git a/storage/myisammrg/plug.in b/storage/myisammrg/plug.in index a2654373fba..22cd5b17cb4 100644 --- a/storage/myisammrg/plug.in +++ b/storage/myisammrg/plug.in @@ -1,5 +1,4 @@ MYSQL_STORAGE_ENGINE(myisammrg,no,[MyISAM MERGE Engine], [Merge multiple MySQL tables into one]) -MYSQL_PLUGIN_DIRECTORY(myisammrg,[storage/myisammrg]) MYSQL_PLUGIN_STATIC(myisammrg, [libmyisammrg_s.la], [libmyisammrg_embedded.la]) MYSQL_PLUGIN_MANDATORY(myisammrg) diff --git a/storage/mysql_storage_engine.cmake b/storage/mysql_storage_engine.cmake index 07b4151c50c..b29ba961179 100644 --- a/storage/mysql_storage_engine.cmake +++ b/storage/mysql_storage_engine.cmake @@ -10,41 +10,41 @@ # ${engine}_LIBS variable containing extra libraries to link with may be set -MACRO(MYSQL_STORAGE_ENGINE engine) +MACRO(MYSQL_PLUGIN engine) IF(NOT SOURCE_SUBLIBS) # Add common include directories - INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib - ${CMAKE_SOURCE_DIR}/sql - ${CMAKE_SOURCE_DIR}/regex - ${CMAKE_SOURCE_DIR}/extra/yassl/include - ${CMAKE_BINARY_DIR}/include - ${CMAKE_BINARY_DIR}/sql - ) + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_BINARY_DIR}/include) STRING(TOUPPER ${engine} engine) - STRING(TOLOWER ${engine} libname) IF(${ENGINE_BUILD_TYPE} STREQUAL "STATIC") - ADD_DEFINITIONS(-DWITH_${engine}_STORAGE_ENGINE -DMYSQL_SERVER) - #Create static library. The name of the library is <storage_engine>.lib - ADD_LIBRARY(${libname} ${${engine}_SOURCES}) - ADD_DEPENDENCIES(${libname} GenError) + ADD_LIBRARY(${${engine}_LIB} ${${engine}_SOURCES}) + ADD_DEPENDENCIES(${${engine}_LIB} GenError) IF(${engine}_LIBS) - TARGET_LINK_LIBRARIES(${libname} ${${engine}_LIBS}) + TARGET_LINK_LIBRARIES(${${engine}_LIB} ${${engine}_LIBS}) ENDIF(${engine}_LIBS) - MESSAGE("build ${engine} as static library") + MESSAGE("build ${engine} as static library (${${engine}_LIB}.lib)") ELSEIF(${ENGINE_BUILD_TYPE} STREQUAL "DYNAMIC") ADD_DEFINITIONS(-DMYSQL_DYNAMIC_PLUGIN) - #Create a DLL.The name of the dll is ha_<storage_engine>.dll - #The dll is linked to the mysqld executable - SET(dyn_libname ha_${libname}) - ADD_VERSION_INFO(${dyn_libname} SHARED ${engine}_SOURCES) - ADD_LIBRARY(${dyn_libname} MODULE ${${engine}_SOURCES}) - TARGET_LINK_LIBRARIES (${dyn_libname} mysqlservices mysqld) + ADD_VERSION_INFO(${${engine}_LIB} SHARED ${engine}_SOURCES) + ADD_LIBRARY(${${engine}_LIB} MODULE ${${engine}_SOURCES}) + TARGET_LINK_LIBRARIES (${${engine}_LIB} mysqlservices mysqld) IF(${engine}_LIBS) - TARGET_LINK_LIBRARIES(${dyn_libname} ${${engine}_LIBS}) + TARGET_LINK_LIBRARIES(${${engine}_LIB} ${${engine}_LIBS}) ENDIF(${engine}_LIBS) # Install the plugin - MYSQL_INSTALL_TARGETS(${dyn_libname} DESTINATION lib/plugin COMPONENT Server) - MESSAGE("build ${engine} as DLL") + MYSQL_INSTALL_TARGETS(${${engine}_LIB} DESTINATION lib/plugin COMPONENT Server) + MESSAGE("build ${engine} as DLL (${${engine}_LIB}.dll)") + ENDIF(${ENGINE_BUILD_TYPE} STREQUAL "STATIC") +ENDIF(NOT SOURCE_SUBLIBS) +ENDMACRO(MYSQL_PLUGIN) + +MACRO(MYSQL_STORAGE_ENGINE engine) +IF(NOT SOURCE_SUBLIBS) + MYSQL_PLUGIN(${engine}) + INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/zlib ${CMAKE_SOURCE_DIR}/sql + ${CMAKE_SOURCE_DIR}/regex ${CMAKE_BINARY_DIR}/sql + ${CMAKE_SOURCE_DIR}/extra/yassl/include) + IF(${ENGINE_BUILD_TYPE} STREQUAL "STATIC") + ADD_DEFINITIONS(-DWITH_${engine}_STORAGE_ENGINE -DMYSQL_SERVER) ENDIF(${ENGINE_BUILD_TYPE} STREQUAL "STATIC") ENDIF(NOT SOURCE_SUBLIBS) ENDMACRO(MYSQL_STORAGE_ENGINE) diff --git a/storage/ndb/plug.in b/storage/ndb/plug.in index 3d3349f7a8b..d5f30d1e4b2 100644 --- a/storage/ndb/plug.in +++ b/storage/ndb/plug.in @@ -1,6 +1,5 @@ MYSQL_STORAGE_ENGINE(ndbcluster, ndbcluster, [Cluster Storage Engine], [High Availability Clustered tables],) -MYSQL_PLUGIN_DIRECTORY(ndbcluster,[storage/ndb]) MYSQL_PLUGIN_STATIC(ndbcluster, [[\$(ndbcluster_libs) \$(ndbcluster_system_libs) \$(NDB_SCI_LIBS)]]) MYSQL_PLUGIN_ACTIONS(ndbcluster,[MYSQL_SETUP_NDBCLUSTER]) MYSQL_PLUGIN_DEPENDS(ndbcluster, [partition]) diff --git a/storage/pbxt/plug.in b/storage/pbxt/plug.in index c0dc06d9702..2d79ad61b3a 100644 --- a/storage/pbxt/plug.in +++ b/storage/pbxt/plug.in @@ -1,6 +1,5 @@ MYSQL_STORAGE_ENGINE(pbxt,no, [PBXT Storage Engine], [MVCC-based transactional engine], [max,max-no-ndb]) -MYSQL_PLUGIN_DIRECTORY(pbxt, [storage/pbxt]) MYSQL_PLUGIN_STATIC(pbxt, [src/libpbxt_s.la], [src/libpbxt_s_embedded.la]) MYSQL_PLUGIN_ACTIONS(pbxt, [ # AC_CONFIG_FILES(storage/pbxt/src/Makefile) diff --git a/storage/xtradb/CMakeLists.txt b/storage/xtradb/CMakeLists.txt index 509f7f0fe73..50f2dba5cf9 100644 --- a/storage/xtradb/CMakeLists.txt +++ b/storage/xtradb/CMakeLists.txt @@ -13,15 +13,9 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# This is the CMakeLists for InnoDB Plugin +# This is the CMakeLists for XtraDB - - -# Starting at 5.1.38, MySQL CMake files are simplified. But the plugin -# CMakeLists.txt still needs to work with previous versions of MySQL. -IF (MYSQL_VERSION_ID GREATER "50137") - INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake") -ENDIF (MYSQL_VERSION_ID GREATER "50137") +INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake") IF (CMAKE_SIZEOF_VOID_P MATCHES 8) SET(WIN64 TRUE) diff --git a/storage/xtradb/plug.in b/storage/xtradb/plug.in index 2e0c873094a..1846543a81c 100644 --- a/storage/xtradb/plug.in +++ b/storage/xtradb/plug.in @@ -16,7 +16,6 @@ MYSQL_STORAGE_ENGINE(xtradb, xtradb, [XtraDB Storage Engine], [XtraDB - a drop-in replacement for InnoDB], [max,max-no-ndb]) -MYSQL_PLUGIN_DIRECTORY(xtradb, [storage/xtradb]) MYSQL_PLUGIN_STATIC(xtradb, [libxtradb.la]) MYSQL_PLUGIN_DYNAMIC(xtradb, [ha_xtradb.la]) MYSQL_PLUGIN_ACTIONS(xtradb, [ diff --git a/win/README b/win/README index 916f64913ac..8ae611ec746 100644 --- a/win/README +++ b/win/README @@ -51,12 +51,10 @@ win\configure <options> The options right now are: - WITH_INNOBASE_STORAGE_ENGINE Enable particular storage engines - WITH_PARTITION_STORAGE_ENGINE - WITH_ARCHIVE_STORAGE_ENGINE - WITH_BLACKHOLE_STORAGE_ENGINE - WITH_EXAMPLE_STORAGE_ENGINE - WITH_FEDERATED_STORAGE_ENGINE + --with-plugin-XXX Enable particular plugin or plugins + --with-plugins=XXX,YYY,... + --with-plugins=GROUP GROUP can be, for example, "max" or "max-no-ndb" + --without-plugin-XXX Disable particular plugin __NT__ Enable named pipe support MYSQL_SERVER_SUFFIX=<suffix> Server suffix, default none COMPILATION_COMMENT=<comment> Server comment, default "Source distribution" @@ -70,7 +68,7 @@ The options right now are: So the command line could look like: -win\configure WITH_INNOBASE_STORAGE_ENGINE WITH_PARTITION_STORAGE_ENGINE MYSQL_SERVER_SUFFIX=-pro +win\configure --with-plugin-innobase --with-plugin-partition MYSQL_SERVER_SUFFIX=-pro Step 6 ------ diff --git a/win/configure-mariadb.bat b/win/configure-mariadb.bat index 6c4283359b4..dc5b59819a3 100644 --- a/win/configure-mariadb.bat +++ b/win/configure-mariadb.bat @@ -5,4 +5,5 @@ cscript win\configure.js ^ WITH_PARTITION_STORAGE_ENGINE ^ WITH_ARIA_STORAGE_ENGINE ^ WITH_PBXT_STORAGE_ENGINE ^ - WITH_XTRADB_STORAGE_ENGINE + WITH_XTRADB_STORAGE_ENGINE ^ + WITH_FEEDBACK_STORAGE_ENGINE diff --git a/win/configure-mariadb.sh b/win/configure-mariadb.sh index 616d1b790d6..67bfe293639 100644 --- a/win/configure-mariadb.sh +++ b/win/configure-mariadb.sh @@ -18,4 +18,5 @@ cscript win/configure.js \ WITH_ARIA_STORAGE_ENGINE \ WITH_PBXT_STORAGE_ENGINE \ WITH_XTRADB_STORAGE_ENGINE \ + WITH_FEEDBACK_STORAGE_ENGINE \ WITH_EMBEDDED_SERVER diff --git a/win/configure.js b/win/configure.js index da7e4c2cd43..43234b39c22 100644 --- a/win/configure.js +++ b/win/configure.js @@ -126,7 +126,7 @@ try var engineOptions = ParsePlugins(); for (option in engineOptions) { - configfile.WriteLine("SET(" + engineOptions[option] + " TRUE)"); + configfile.WriteLine("SET (" + engineOptions[option] + " TRUE)"); } configfile.Close(); @@ -302,7 +302,7 @@ function ParsePlugins() { var content = fso.OpenTextFile(filename, ForReading).ReadAll(); var match = - /MYSQL_STORAGE_ENGINE([ ]*)[\(]([^\)]+)[\)]/.exec(content); + /MYSQL_(PLUGIN|STORAGE_ENGINE)([ ]*)[\(]([^\)]+)[\)]/.exec(content); if (match== null) continue; match = /\[[\w,\-_]+\][\s]?\)/.exec(match[0]); @@ -329,9 +329,9 @@ function ParsePlugins() for(key in config) { var eng = config[key]; - if(eng.isGroup != undefined && !eng.isGroup && eng.include != undefined) + if(eng.isGroup != undefined && !eng.isGroup && eng.include != undefined) { - if (fso.FolderExists("storage\\"+key) || key=="PARTITION") + if (fso.FolderExists("storage\\"+key) || fso.FolderExists("plugin\\"+key) || key=="PARTITION") { arr[arr.length] = eng.include? "WITH_"+key+"_STORAGE_ENGINE":"WITHOUT_"+key+"_STORAGE_ENGINE"; |