merge with 5.1
This commit is contained in:
commit
eeca1f8694
@ -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
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -16,13 +16,27 @@
|
||||
#ifndef _my_plugin_h
|
||||
#define _my_plugin_h
|
||||
|
||||
|
||||
/*
|
||||
On Windows, exports from DLL need to be declared
|
||||
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(_WIN32) && defined(MYSQL_DYNAMIC_PLUGIN))
|
||||
#define MYSQL_PLUGIN_EXPORT extern "C" __declspec(dllexport)
|
||||
#else
|
||||
#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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
||||
|
13
mysql-test/r/feedback_plugin_install.result
Normal file
13
mysql-test/r/feedback_plugin_install.result
Normal file
@ -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;
|
11
mysql-test/r/feedback_plugin_load.result
Normal file
11
mysql-test/r/feedback_plugin_load.result
Normal file
@ -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
|
15
mysql-test/r/feedback_plugin_send.result
Normal file
15
mysql-test/r/feedback_plugin_send.result
Normal file
@ -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'
|
1
mysql-test/t/feedback_plugin_install.opt
Normal file
1
mysql-test/t/feedback_plugin_install.opt
Normal file
@ -0,0 +1 @@
|
||||
--loose-feedback
|
15
mysql-test/t/feedback_plugin_install.test
Normal file
15
mysql-test/t/feedback_plugin_install.test
Normal file
@ -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;
|
||||
|
2
mysql-test/t/feedback_plugin_load.opt
Normal file
2
mysql-test/t/feedback_plugin_load.opt
Normal file
@ -0,0 +1,2 @@
|
||||
--loose-feedback
|
||||
--plugin-load=$FEEDBACK_SO
|
10
mysql-test/t/feedback_plugin_load.test
Normal file
10
mysql-test/t/feedback_plugin_load.test
Normal file
@ -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';
|
24
mysql-test/t/feedback_plugin_send.test
Normal file
24
mysql-test/t/feedback_plugin_send.test
Normal file
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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]);
|
||||
|
11
plugin/feedback/CMakeLists.txt
Normal file
11
plugin/feedback/CMakeLists.txt
Normal file
@ -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)
|
18
plugin/feedback/Makefile.am
Normal file
18
plugin/feedback/Makefile.am
Normal file
@ -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
|
||||
|
355
plugin/feedback/feedback.cc
Normal file
355
plugin/feedback/feedback.cc
Normal file
@ -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;
|
||||
|
67
plugin/feedback/feedback.h
Normal file
67
plugin/feedback/feedback.h
Normal file
@ -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
|
||||
|
28
plugin/feedback/plug.in
Normal file
28
plugin/feedback/plug.in
Normal file
@ -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])
|
||||
])
|
||||
|
301
plugin/feedback/sender_thread.cc
Normal file
301
plugin/feedback/sender_thread.cc
Normal file
@ -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
|
||||
|
51
plugin/feedback/url_base.cc
Normal file
51
plugin/feedback/url_base.cc
Normal file
@ -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
|
303
plugin/feedback/url_http.cc
Normal file
303
plugin/feedback/url_http.cc
Normal file
@ -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
|
||||
|
387
plugin/feedback/utils.cc
Normal file
387
plugin/feedback/utils.cc
Normal file
@ -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
|
3
plugin/fulltext/CMakeLists.txt
Normal file
3
plugin/fulltext/CMakeLists.txt
Normal file
@ -0,0 +1,3 @@
|
||||
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
|
||||
SET(FTEXAMPLE_SOURCES plugin_example.c)
|
||||
MYSQL_PLUGIN(FTEXAMPLE)
|
@ -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
|
||||
|
@ -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} */
|
||||
|
@ -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])
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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, [
|
||||
|
@ -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])
|
||||
|
@ -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)
|
||||
|
@ -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, [
|
||||
|
@ -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)
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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])
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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, [
|
||||
|
12
win/README
12
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
|
||||
------
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
|
Loading…
x
Reference in New Issue
Block a user