Commit d554a6c1 authored by Sergei Golubchik's avatar Sergei Golubchik

merge the feedback tree

parents 1351bef4 c9783670
......@@ -1952,3 +1952,8 @@ scripts/convert-debug-for-diff
client/strings_def.h
libmysql/strings_def.h
libmysql_r/strings_def.h
CPackConfig.cmake
CPackSourceConfig.cmake
win/nmake_cache.txt
*.manifest
*.resource.txt
......@@ -172,6 +172,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")
......@@ -313,16 +316,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)
......@@ -331,20 +333,22 @@ 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)
......@@ -359,15 +363,17 @@ FOREACH(SUBDIR ${STORAGE_SUBDIRS})
ENDIF(WITH_${ENGINE}_STORAGE_ENGINE AND MYSQL_PLUGIN_STATIC)
IF (ENGINE_BUILD_TYPE STREQUAL "STATIC")
SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_${PLUGIN_NAME}_plugin")
SET (MYSQLD_STATIC_ENGINE_LIBS ${MYSQLD_STATIC_ENGINE_LIBS} ${PLUGIN_NAME})
SET (mysql_plugin_defs "${mysql_plugin_defs},builtin_${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")
......
......@@ -864,7 +864,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
*/
#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
......
......@@ -85,15 +85,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)
......@@ -160,16 +158,15 @@ 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)
INSTALL(TARGETS mysqlserver DESTINATION Embedded/static 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
......
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_SEND_RETRY_WAIT 60
FEEDBACK_USER_INFO mysql-test
FEEDBACK_SEND_TIMEOUT 60
FEEDBACK_URL http://mariadb.org/feedback_plugin/post
FEEDBACK 1.0
uninstall plugin feedback;
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_SEND_RETRY_WAIT 60
FEEDBACK_USER_INFO mysql-test
FEEDBACK_SEND_TIMEOUT 60
FEEDBACK_URL http://mariadb.org/feedback_plugin/post
FEEDBACK 1.0
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_SEND_RETRY_WAIT 60
FEEDBACK_USER_INFO mysql-test
FEEDBACK_SEND_TIMEOUT 60
FEEDBACK_URL http://mariadb.org/feedback_plugin/post
FEEDBACK 1.0
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'
--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
select * from information_schema.feedback where variable_name like 'feed%'
and variable_name not like '%_uid';
uninstall plugin feedback;
--loose-feedback
--plugin-load=$FEEDBACK_SO
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
select * from information_schema.feedback where variable_name like 'feed%'
and variable_name not like '%_uid';
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,6 +48,7 @@ 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)
INSTALL(TARGETS mysys DESTINATION lib/opt COMPONENT runtime) # TODO: Component?
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]);
......
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)
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)
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
/* 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;
/* 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
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])
])
/* 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->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
/* 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
/* 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
/* 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
INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake")
SET(FTEXAMPLE_SOURCES plugin_example.c)
MYSQL_PLUGIN(FTEXAMPLE)
......@@ -3176,6 +3176,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)
......@@ -3332,6 +3345,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} */
......
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])
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
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
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])
......
......@@ -48,37 +48,37 @@ SET(MARIA_SOURCES ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c
MYSQL_STORAGE_ENGINE(MARIA)
IF(NOT SOURCE_SUBLIBS)
ADD_DEPENDENCIES(maria GenError)
ADD_DEPENDENCIES(libmaria_s GenError)
ADD_EXECUTABLE(maria_ftdump maria_ftdump.c)
TARGET_LINK_LIBRARIES(maria_ftdump maria myisam mysys dbug strings zlib wsock32)
TARGET_LINK_LIBRARIES(maria_ftdump libmaria_s libmyisam_s mysys dbug strings zlib wsock32)
ADD_EXECUTABLE(maria_chk maria_chk.c)
TARGET_LINK_LIBRARIES(maria_chk maria myisam mysys dbug strings zlib wsock32)
TARGET_LINK_LIBRARIES(maria_chk libmaria_s libmyisam_s mysys dbug strings zlib wsock32)
ADD_EXECUTABLE(maria_read_log maria_read_log.c)
TARGET_LINK_LIBRARIES(maria_read_log maria myisam mysys dbug strings zlib wsock32)
TARGET_LINK_LIBRARIES(maria_read_log libmaria_s libmyisam_s mysys dbug strings zlib wsock32)
ADD_EXECUTABLE(maria_pack maria_pack.c)
TARGET_LINK_LIBRARIES(maria_pack maria myisam mysys dbug strings zlib wsock32)
TARGET_LINK_LIBRARIES(maria_pack libmaria_s libmyisam_s mysys dbug strings zlib wsock32)
ADD_EXECUTABLE(maria_dump_log maria_dump_log.c unittest/ma_loghandler_examples.c)
TARGET_LINK_LIBRARIES(maria_dump_log maria myisam mysys dbug strings zlib wsock32)
TARGET_LINK_LIBRARIES(maria_dump_log libmaria_s libmyisam_s mysys dbug strings zlib wsock32)
ADD_EXECUTABLE(ma_test1 ma_test1.c)
TARGET_LINK_LIBRARIES(ma_test1 maria myisam mysys dbug strings zlib wsock32)
TARGET_LINK_LIBRARIES(ma_test1 libmaria_s libmyisam_s mysys dbug strings zlib wsock32)
ADD_EXECUTABLE(ma_test2 ma_test2.c)
TARGET_LINK_LIBRARIES(ma_test2 maria myisam mysys dbug strings zlib wsock32)
TARGET_LINK_LIBRARIES(ma_test2 libmaria_s libmyisam_s mysys dbug strings zlib wsock32)
ADD_EXECUTABLE(ma_test3 ma_test3.c)
TARGET_LINK_LIBRARIES(ma_test3 maria myisam mysys dbug strings zlib wsock32)
TARGET_LINK_LIBRARIES(ma_test3 libmaria_s libmyisam_s mysys dbug strings zlib wsock32)
ADD_EXECUTABLE(ma_rt_test ma_rt_test.c)
TARGET_LINK_LIBRARIES(ma_rt_test maria myisam mysys dbug strings zlib wsock32)
TARGET_LINK_LIBRARIES(ma_rt_test libmaria_s libmyisam_s mysys dbug strings zlib wsock32)
ADD_EXECUTABLE(ma_sp_test ma_sp_test.c)
TARGET_LINK_LIBRARIES(ma_sp_test maria myisam mysys dbug strings zlib wsock32)
TARGET_LINK_LIBRARIES(ma_sp_test libmaria_s libmyisam_s mysys dbug strings zlib wsock32)
IF(EMBED_MANIFESTS)
MYSQL_EMBED_MANIFEST("maria_ftdump" "asInvoker")
......
MYSQL_STORAGE_ENGINE(maria,, [Maria Storage Engine],
[Crash-safe tables with MyISAM heritage], [default,max,max-no-ndb])
MYSQL_PLUGIN_DIRECTORY(maria, [storage/maria])
MYSQL_PLUGIN_STATIC(maria, [libmaria_s.la], [libmaria_embedded.la])
# Maria will probably go first into max builds, not all builds,
# so we don't declare it mandatory.
......
......@@ -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)
ADD_EXECUTABLE(myisam_ftdump myisam_ftdump.c)
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)
ADD_EXECUTABLE(myisamchk myisamchk.c)
TARGET_LINK_LIBRARIES(myisamchk myisam mysys debug dbug strings zlib wsock32)
TARGET_LINK_LIBRARIES(myisamchk libmyisam_s mysys debug dbug strings zlib wsock32)
ADD_EXECUTABLE(myisamlog myisamlog.c)
TARGET_LINK_LIBRARIES(myisamlog myisam mysys debug dbug strings zlib wsock32)
TARGET_LINK_LIBRARIES(myisamlog libmyisam_s mysys debug dbug strings zlib wsock32)
ADD_EXECUTABLE(myisampack myisampack.c)
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")
......
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
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,37 +10,40 @@
# ${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)
INCLUDE_DIRECTORIES(${CMAKE_SOURCE_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_LIBRARY(${dyn_libname} SHARED ${${engine}_SOURCES})
TARGET_LINK_LIBRARIES (${dyn_libname} mysqld)
ADD_LIBRARY(${${engine}_LIB} SHARED ${${engine}_SOURCES})
TARGET_LINK_LIBRARIES (${${engine}_LIB} mysqld)
IF(${engine}_LIBS)
TARGET_LINK_LIBRARIES(${dyn_libname} ${${engine}_LIBS})
TARGET_LINK_LIBRARIES(${${engine}_LIB} ${${engine}_LIBS})
ENDIF(${engine}_LIBS)
# Install the plugin
INSTALL(TARGETS ${dyn_libname} DESTINATION lib/plugin COMPONENT runtime)
MESSAGE("build ${engine} as DLL")
INSTALL(TARGETS ${${engine}_LIB} DESTINATION lib/plugin COMPONENT runtime)
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_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)
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])
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, [
......
......@@ -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_MARIA_STORAGE_ENGINE ^
WITH_PBXT_STORAGE_ENGINE ^
WITH_XTRADB_STORAGE_ENGINE
WITH_XTRADB_STORAGE_ENGINE ^
WITH_FEEDBACK_STORAGE_ENGINE
......@@ -7,17 +7,9 @@
set -e
cscript win/configure.js \
WITH_ARCHIVE_STORAGE_ENGINE \
WITH_BLACKHOLE_STORAGE_ENGINE \
WITH_CSV_STORAGE_ENGINE \
WITH_EXAMPLE_STORAGE_ENGINE \
WITH_FEDERATEDX_STORAGE_ENGINE \
WITH_MERGE_STORAGE_ENGINE \
WITH_PARTITION_STORAGE_ENGINE \
WITH_MARIA_STORAGE_ENGINE \
WITH_PBXT_STORAGE_ENGINE \
WITH_XTRADB_STORAGE_ENGINE \
cscript win/configure.js --with-plugin-archive --with-plugin-blackhole \
--with-plugin-csv --with-plugin-example --with-plugin-federatedx \
--with-plugin-merge --with-plugin-partition --with-plugin-maria \
--with-plugin-pbxt --with-plugin-xtradb --with-plugin-feedback \
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]);
......@@ -331,7 +331,7 @@ function ParsePlugins()
var eng = config[key];
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";
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment