From 4c34bcf8562fac61a918c6364e3bbbe385e8505d Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Sat, 1 Oct 2011 21:23:01 +0200 Subject: [PATCH 01/12] initial checkin --- CMakeLists.txt | 11 ++ Makefile.am | 19 +++ feedback.cc | 349 +++++++++++++++++++++++++++++++++++++++++++++++ feedback.h | 67 +++++++++ plug.in | 19 +++ sender_thread.cc | 294 +++++++++++++++++++++++++++++++++++++++ url_base.cc | 51 +++++++ url_http.cc | 308 +++++++++++++++++++++++++++++++++++++++++ utils.cc | 299 ++++++++++++++++++++++++++++++++++++++++ 9 files changed, 1417 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 Makefile.am create mode 100644 feedback.cc create mode 100644 feedback.h create mode 100644 plug.in create mode 100644 sender_thread.cc create mode 100644 url_base.cc create mode 100644 url_http.cc create mode 100644 utils.cc diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000000..a94232a4698 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,11 @@ +INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake") + +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/sql ${CMAKE_SOURCE_DIR}/regex + ${CMAKE_SOURCE_DIR}/extra/yassl/include) + +SET(FEEDBACK_SOURCES feedback.cc sender_thread.cc + url_base.cc url_http.cc utils.cc) + +SET(FEEDBACK_LIBS Ws2_32) + +MYSQL_PLUGIN(FEEDBACK) diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000000..0aea977b464 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,19 @@ +pkgplugindir = $(pkglibdir)/plugin +INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \ + -I$(top_srcdir)/regex -I$(top_srcdir)/sql + +EXTRA_LTLIBRARIES = feedback.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 + +EXTRA_LIBRARIES = libfeedback.a +noinst_LIBRARIES = @plugin_feedback_static_target@ +libfeedback_a_SOURCES= feedback.cc utils.cc url_base.cc url_http.cc \ + sender_thread.cc + +noinst_HEADERS = feedback.h +EXTRA_DIST = CMakeLists.txt plug.in + diff --git a/feedback.cc b/feedback.cc new file mode 100644 index 00000000000..89fe981cc25 --- /dev/null +++ b/feedback.cc @@ -0,0 +1,349 @@ +/* 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; +} + +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, + "https://mariadb.org/feedback_plugin/post"); +static MYSQL_SYSVAR_ULONG(send_timeout, send_timeout, PLUGIN_VAR_RQCMDARG, + "Timeout (in seconds) for the sending the report.", + NULL, NULL, 60, 1, 60*60*24, 1); +static MYSQL_SYSVAR_ULONG(send_retry_wait, send_retry_wait, PLUGIN_VAR_RQCMDARG, + "Wait this many seconds before retrying a failed send.", + NULL, NULL, 60, 1, 60*60*24, 1); + +static struct st_mysql_sys_var* settings[] = { + MYSQL_SYSVAR(server_uid), + MYSQL_SYSVAR(user_info), + MYSQL_SYSVAR(url), + MYSQL_SYSVAR(send_timeout), + MYSQL_SYSVAR(send_retry_wait), + NULL +}; + + +static struct st_mysql_information_schema feedback = +{ MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION }; + +} // namespace feedback + +mysql_declare_plugin(feedback) +{ + MYSQL_INFORMATION_SCHEMA_PLUGIN, + &feedback::feedback, + "FEEDBACK", + "Sergei Golubchik", + "MariaDB User Feedback Plugin", + PLUGIN_LICENSE_GPL, + feedback::init, + feedback::free, + 0x0100, + NULL, + feedback::settings, + NULL +} +mysql_declare_plugin_end; + diff --git a/feedback.h b/feedback.h new file mode 100644 index 00000000000..60ef72eed84 --- /dev/null +++ b/feedback.h @@ -0,0 +1,67 @@ +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#define MYSQL_SERVER +#include + +namespace feedback { + +int fill_feedback(THD *thd, TABLE_LIST *tables, COND *cond); +int fill_plugin_version(THD *thd, TABLE_LIST *tables); +int fill_misc_data(THD *thd, TABLE_LIST *tables); +int fill_linux_info(THD *thd, TABLE_LIST *tables); + +static const int SERVER_UID_SIZE= 29; +extern char server_uid_buf[SERVER_UID_SIZE+1], *user_info; +int calculate_server_uid(char *); +int prepare_linux_info(); + +extern ST_SCHEMA_TABLE *i_s_feedback; + +extern ulong send_timeout, send_retry_wait; + +pthread_handler_t background_thread(void *arg); + +/** + The class for storing urls to send report data to. + + Constructors are private, the object should be created with create() method. + send() method does the actual sending. +*/ +class Url { + protected: + Url(LEX_STRING &url_arg) : full_url(url_arg) {} + const LEX_STRING full_url; + + public: + virtual ~Url() { my_free(full_url.str, MYF(0)); } + + const char *url() { return full_url.str; } + size_t url_length() { return full_url.length; } + virtual int send(const char* data, size_t data_length) = 0; + + static Url* create(const char *url, size_t url_length); +}; + +extern Url **urls; +extern uint url_count; + +/* these are used to communicate with the background thread */ +extern pthread_mutex_t sleep_mutex; +extern pthread_cond_t sleep_condition; +extern volatile bool shutdown_plugin; + +} // namespace feedback + diff --git a/plug.in b/plug.in new file mode 100644 index 00000000000..0c93fef2327 --- /dev/null +++ b/plug.in @@ -0,0 +1,19 @@ +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]) +MYSQL_PLUGIN_STATIC(feedback, [libfeedback.a]) + +MYSQL_PLUGIN_ACTIONS(feedback, [ + AC_CHECK_HEADERS([netdb.h sys/utsname.h]) +]) + diff --git a/sender_thread.cc b/sender_thread.cc new file mode 100644 index 00000000000..813690b8819 --- /dev/null +++ b/sender_thread.cc @@ -0,0 +1,294 @@ +/* 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 + +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 next_interval= 60*60*24*7; ///< in seconds (one week) +static const time_t first_interval= 60*60*24; ///< in seconds (one day) + +/** + 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 delay(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(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 (delay(send_retry_wait) == 0); // 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))) +{ + time_t interval; + + if (my_thread_init()) + return 0; + + pthread_mutex_lock(&LOCK_thread_count); + thd_thread_id= thread_id++; + pthread_mutex_unlock(&LOCK_thread_count); + + send_report("startup"); + + for (interval= first_interval; delay(interval) == 0; interval= next_interval) + send_report(NULL); + + send_report("shutdown"); + + my_thread_end(); + pthread_exit(0); + return 0; +} + +} // namespace feedback + diff --git a/url_base.cc b/url_base.cc new file mode 100644 index 00000000000..38b2ca86e9f --- /dev/null +++ b/url_base.cc @@ -0,0 +1,51 @@ +/* Copyright (C) 2010 Sergei Golubchik and Monty Program Ab + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + +#include "feedback.h" + +namespace feedback { + +Url* http_create(const char *url, size_t url_length); + +/** + creates an Url object out of an url, if possible. + + This is done by invoking corresponding creator functions + of the derived classes, until the first not NULL result. +*/ +Url* Url::create(const char *url, size_t url_length) +{ + url= my_strndup(url, url_length, MYF(MY_WME)); + + if (!url) + return NULL; + + Url *self= http_create(url, url_length); + + /* + here we can add + + if (!self) self= smtp_create(url, url_length); + if (!self) self= tftp_create(url, url_length); + etc + */ + + if (!self) + my_free(const_cast(url), MYF(0)); + + return self; +} + +} // namespace feedback diff --git a/url_http.cc b/url_http.cc new file mode 100644 index 00000000000..efe987327d3 --- /dev/null +++ b/url_http.cc @@ -0,0 +1,308 @@ +/* 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 +#endif + +#ifdef _WIN32 +#undef VOID +#define VOID void +#include +#define addrinfo ADDRINFOA +#endif + +namespace feedback { + +static const char *http= "http://"; +static const size_t http_len= 7; +static const char *https= "https://"; +static const size_t https_len= 8; + +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(url), url_length}; + LEX_STRING host, port, path; + bool ssl= false; + + if (is_prefix(url, http)) + s= url + http_len; +#ifdef HAVE_OPENSSL + else if (is_prefix(url, https)) + { + ssl= true; + s= url + https_len; + } +#endif + else + return NULL; + + for (url= s; *s && *s != ':' && *s != '/'; s++) /* no-op */; + host.str= const_cast(url); + host.length= s-url; + + if (*s == ':') + { + for (url= ++s; *s && *s >= '0' && *s <= '9'; s++) /* no-op */; + port.str= const_cast(url); + port.length= s-url; + } + else + { + if (ssl) + { + port.str= const_cast("443"); + port.length=3; + } + else + { + port.str= const_cast("80"); + port.length=2; + } + } + + if (*s == 0) + { + path.str= const_cast("/"); + path.length= 1; + } + else + { + path.str= const_cast(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

...

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, "

"))) + { + from+= 4; + char *to= strstr(from, "

"); + if (to) + *to= 0; + else + from= NULL; + } + if (from) + sql_print_information("feedback plugin: server replied '%s'", from); + else + sql_print_warning("feedback plugin: failed to parse server reply"); + } + else + { + res= 1; + sql_print_error("feedback plugin: failed to read server reply"); + } + } + + vio_delete(vio); + +#ifdef HAVE_OPENSSL + if (ssl) + { + SSL_CTX_free(ssl_fd->ssl_context); + my_free(ssl_fd, MYF(0)); + } +#endif + + return res; +} + +} // namespace feedback + diff --git a/utils.cc b/utils.cc new file mode 100644 index 00000000000..f5afd427ebf --- /dev/null +++ b/utils.cc @@ -0,0 +1,299 @@ +/* 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 +#endif + +#include +#include + +#ifdef HAVE_SYS_UTSNAME_H +#include +static bool have_ubuf= false; +static struct utsname ubuf; +#endif + +#ifdef TARGET_OS_LINUX +#include +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); +#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 From 9401ae94251d08442402e86df61c2e0c8d3809a4 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Mon, 3 Oct 2011 08:43:01 +0200 Subject: [PATCH 02/12] don't use https url by default, if ssl is not available --- feedback.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/feedback.cc b/feedback.cc index 89fe981cc25..056484ab46e 100644 --- a/feedback.cc +++ b/feedback.cc @@ -298,6 +298,12 @@ static int free(void *p) 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); @@ -307,7 +313,7 @@ static MYSQL_SYSVAR_STR(user_info, user_info, 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, - "https://mariadb.org/feedback_plugin/post"); + 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); From 45ee26699ee107b78aecb8d5a9afb46e4bebfa89 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 4 Oct 2011 15:01:26 +0200 Subject: [PATCH 03/12] remove redundant declarations --- storage/blackhole/plug.in | 1 - storage/csv/plug.in | 1 - storage/heap/plug.in | 1 - storage/innobase/plug.in.disabled | 1 - storage/innodb_plugin/plug.in | 1 - storage/maria/plug.in | 1 - storage/myisam/plug.in | 1 - storage/myisammrg/plug.in | 1 - storage/ndb/plug.in | 1 - storage/pbxt/plug.in | 1 - storage/xtradb/plug.in | 1 - 11 files changed, 11 deletions(-) diff --git a/storage/blackhole/plug.in b/storage/blackhole/plug.in index 2f3b120fa5d..84b7299969b 100644 --- a/storage/blackhole/plug.in +++ b/storage/blackhole/plug.in @@ -1,6 +1,5 @@ MYSQL_STORAGE_ENGINE(blackhole,,[Blackhole Storage Engine], [Basic Write-only Read-never tables], [max,max-no-ndb]) -MYSQL_PLUGIN_DIRECTORY(blackhole, [storage/blackhole]) MYSQL_PLUGIN_STATIC(blackhole, [libblackhole.la]) MYSQL_PLUGIN_DYNAMIC(blackhole, [ha_blackhole.la]) diff --git a/storage/csv/plug.in b/storage/csv/plug.in index 4ff32959fa2..eb4bd4d9883 100644 --- a/storage/csv/plug.in +++ b/storage/csv/plug.in @@ -1,5 +1,4 @@ MYSQL_STORAGE_ENGINE(csv,, [CSV Storage Engine], [Stores tables in text CSV format]) -MYSQL_PLUGIN_DIRECTORY(csv, [storage/csv]) MYSQL_PLUGIN_STATIC(csv, [libcsv.la]) MYSQL_PLUGIN_MANDATORY(csv) dnl Used for logging diff --git a/storage/heap/plug.in b/storage/heap/plug.in index 92ec01d3c88..f1b02b38c2b 100644 --- a/storage/heap/plug.in +++ b/storage/heap/plug.in @@ -1,6 +1,5 @@ MYSQL_STORAGE_ENGINE(heap,no, [Memory Storage Engine], [Volatile memory based tables]) -MYSQL_PLUGIN_DIRECTORY(heap, [storage/heap]) MYSQL_PLUGIN_STATIC(heap, [libheap_s.la], [libheap_embedded.la]) MYSQL_PLUGIN_MANDATORY(heap) dnl Memory tables diff --git a/storage/innobase/plug.in.disabled b/storage/innobase/plug.in.disabled index b18950b9c7a..2d6af1d2883 100644 --- a/storage/innobase/plug.in.disabled +++ b/storage/innobase/plug.in.disabled @@ -1,6 +1,5 @@ MYSQL_STORAGE_ENGINE(innobase, innodb, [InnoDB Storage Engine], [Transactional Tables using InnoDB], [max,max-no-ndb]) -MYSQL_PLUGIN_DIRECTORY(innobase, [storage/innobase]) MYSQL_PLUGIN_STATIC(innobase, [libinnobase.la]) MYSQL_PLUGIN_DYNAMIC(innobase, [ha_innodb.la]) MYSQL_PLUGIN_ACTIONS(innobase, [ diff --git a/storage/innodb_plugin/plug.in b/storage/innodb_plugin/plug.in index ebaa3f574a0..e5e2def5435 100644 --- a/storage/innodb_plugin/plug.in +++ b/storage/innodb_plugin/plug.in @@ -16,7 +16,6 @@ MYSQL_STORAGE_ENGINE(innodb_plugin,, [InnoDB Storage Engine], [Transactional Tables using InnoDB], []) -MYSQL_PLUGIN_DIRECTORY(innodb_plugin, [storage/innodb_plugin]) # Enable if you know what you are doing (trying to link both InnoDB and # InnoDB Plugin statically into MySQL does not work). #MYSQL_PLUGIN_STATIC(innodb_plugin, [libinnobase.a]) diff --git a/storage/maria/plug.in b/storage/maria/plug.in index bdf1ca7a5bf..f7c54da2190 100644 --- a/storage/maria/plug.in +++ b/storage/maria/plug.in @@ -1,6 +1,5 @@ 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. diff --git a/storage/myisam/plug.in b/storage/myisam/plug.in index 95b29336493..0ec7ea1e1d2 100644 --- a/storage/myisam/plug.in +++ b/storage/myisam/plug.in @@ -1,6 +1,5 @@ dnl MYSQL_STORAGE_ENGINE(myisam,no, [MyISAM Storage Engine], dnl [Traditional non-transactional MySQL tables]) -dnl MYSQL_PLUGIN_DIRECTORY(myisam, [storage/myisam]) dnl MYSQL_PLUGIN_STATIC(myisam, [libmyisam_s.la], [libmyisam_embedded.la]) dnl MYSQL_PLUGIN_MANDATORY(myisam) dnl Default diff --git a/storage/myisammrg/plug.in b/storage/myisammrg/plug.in index a2654373fba..22cd5b17cb4 100644 --- a/storage/myisammrg/plug.in +++ b/storage/myisammrg/plug.in @@ -1,5 +1,4 @@ MYSQL_STORAGE_ENGINE(myisammrg,no,[MyISAM MERGE Engine], [Merge multiple MySQL tables into one]) -MYSQL_PLUGIN_DIRECTORY(myisammrg,[storage/myisammrg]) MYSQL_PLUGIN_STATIC(myisammrg, [libmyisammrg_s.la], [libmyisammrg_embedded.la]) MYSQL_PLUGIN_MANDATORY(myisammrg) diff --git a/storage/ndb/plug.in b/storage/ndb/plug.in index 3d3349f7a8b..d5f30d1e4b2 100644 --- a/storage/ndb/plug.in +++ b/storage/ndb/plug.in @@ -1,6 +1,5 @@ MYSQL_STORAGE_ENGINE(ndbcluster, ndbcluster, [Cluster Storage Engine], [High Availability Clustered tables],) -MYSQL_PLUGIN_DIRECTORY(ndbcluster,[storage/ndb]) MYSQL_PLUGIN_STATIC(ndbcluster, [[\$(ndbcluster_libs) \$(ndbcluster_system_libs) \$(NDB_SCI_LIBS)]]) MYSQL_PLUGIN_ACTIONS(ndbcluster,[MYSQL_SETUP_NDBCLUSTER]) MYSQL_PLUGIN_DEPENDS(ndbcluster, [partition]) diff --git a/storage/pbxt/plug.in b/storage/pbxt/plug.in index c0dc06d9702..2d79ad61b3a 100644 --- a/storage/pbxt/plug.in +++ b/storage/pbxt/plug.in @@ -1,6 +1,5 @@ MYSQL_STORAGE_ENGINE(pbxt,no, [PBXT Storage Engine], [MVCC-based transactional engine], [max,max-no-ndb]) -MYSQL_PLUGIN_DIRECTORY(pbxt, [storage/pbxt]) MYSQL_PLUGIN_STATIC(pbxt, [src/libpbxt_s.la], [src/libpbxt_s_embedded.la]) MYSQL_PLUGIN_ACTIONS(pbxt, [ # AC_CONFIG_FILES(storage/pbxt/src/Makefile) diff --git a/storage/xtradb/plug.in b/storage/xtradb/plug.in index 2e0c873094a..1846543a81c 100644 --- a/storage/xtradb/plug.in +++ b/storage/xtradb/plug.in @@ -16,7 +16,6 @@ MYSQL_STORAGE_ENGINE(xtradb, xtradb, [XtraDB Storage Engine], [XtraDB - a drop-in replacement for InnoDB], [max,max-no-ndb]) -MYSQL_PLUGIN_DIRECTORY(xtradb, [storage/xtradb]) MYSQL_PLUGIN_STATIC(xtradb, [libxtradb.la]) MYSQL_PLUGIN_DYNAMIC(xtradb, [ha_xtradb.la]) MYSQL_PLUGIN_ACTIONS(xtradb, [ From f3523559aaa5d6523d907d69de544ee24c9e6915 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 4 Oct 2011 15:07:55 +0200 Subject: [PATCH 04/12] my_gethwaddr() on Solaris and Windows --- configure.in | 2 +- mysys/CMakeLists.txt | 1 + mysys/my_gethwaddr.c | 106 ++++++++++++++++++++++++++++++++++--------- 3 files changed, 87 insertions(+), 22 deletions(-) diff --git a/configure.in b/configure.in index ec5edce9535..75d829330f7 100644 --- a/configure.in +++ b/configure.in @@ -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 \ diff --git a/mysys/CMakeLists.txt b/mysys/CMakeLists.txt index cbb30594a0d..9a911b7bb79 100644 --- a/mysys/CMakeLists.txt +++ b/mysys/CMakeLists.txt @@ -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) diff --git a/mysys/my_gethwaddr.c b/mysys/my_gethwaddr.c index 90908bd1c0d..bcc231eaf7e 100644 --- a/mysys/my_gethwaddr.c +++ b/mysys/my_gethwaddr.c @@ -16,11 +16,22 @@ /* get hardware address for an interface */ /* if there are many available, any non-zero one can be used */ +#define DONT_DEFINE_VOID /* windows includes break if we do */ #include "mysys_priv.h" #include #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 @@ -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 #include -#include +#include +#ifdef HAVE_SYS_SOCKIO_H +#include +#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 +#include + +#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]); From 630b0b877937cfd564251a66d2e0166182bff4ff Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 4 Oct 2011 15:41:52 +0200 Subject: [PATCH 05/12] support for plugins on windows CMakeLists.txt: 1. add -DSAFEMALLOC -DSAFE_MUTEX in the top-level CMakeLists.txt don't force plugins to copy-paste these lines in their CMakeLists.txt 2.1 search plugin/* for plugins (not only storage/*), 2.2 recognize MYSQL_PLUGIN (not only MYSQL_STORAGE_ENGINE), 2.3 extract library names from the plug.in (don't force library names to be ha_.dll and .lib) include/mysql/plugin.h: define MYSQL_PLUGIN_EXPORT appropriately (backport from 5.5) libmysqld/CMakeLists.txt: remove unnecessary workaround plugin/fulltext/CMakeLists.txt: build fulltext example plugin on windows storage/maria/CMakeLists.txt: The library is called libmaria_s.lib, not maria.lib storage/maria/unittest/CMakeLists.txt: The library is called libmaria_s.lib, not maria.lib storage/myisam/CMakeLists.txt: The library is called libmyisam_s.lib, not myisam.lib storage/mysql_storage_engine.cmake: introduce MYSQL_PLUGIN macro. don't force library names to be ha_.dll and .lib storage/xtradb/CMakeLists.txt: remove a condition from include win/README: don't use deprecated syntax win/configure-mariadb.sh: don't use deprecated syntax win/configure.js: 1. support MYSQL_PLUGIN in addition to MYSQL_STORAGE_ENGINE. 2. support plugin/* in addition to storage/* --- .bzrignore | 5 +++ CMakeLists.txt | 48 +++++++++++++++------------ include/mysql/plugin.h | 22 +++++++++--- libmysqld/CMakeLists.txt | 27 +++++++-------- plugin/fulltext/CMakeLists.txt | 3 ++ storage/maria/CMakeLists.txt | 22 ++++++------ storage/maria/unittest/CMakeLists.txt | 3 +- storage/myisam/CMakeLists.txt | 18 +++++----- storage/mysql_storage_engine.cmake | 43 +++++++++++++----------- storage/xtradb/CMakeLists.txt | 10 ++---- win/README | 12 +++---- win/configure-mariadb.bat | 3 +- win/configure-mariadb.sh | 16 +++------ win/configure.js | 8 ++--- 14 files changed, 126 insertions(+), 114 deletions(-) create mode 100644 plugin/fulltext/CMakeLists.txt diff --git a/.bzrignore b/.bzrignore index b2dd8a9447c..84ebe547912 100644 --- a/.bzrignore +++ b/.bzrignore @@ -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 diff --git a/CMakeLists.txt b/CMakeLists.txt index 4954e4a9d07..11e24652b33 100755 --- a/CMakeLists.txt +++ b/CMakeLists.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,21 +333,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) @@ -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") diff --git a/include/mysql/plugin.h b/include/mysql/plugin.h index e1852f2929e..cd46f3ff5e8 100644 --- a/include/mysql/plugin.h +++ b/include/mysql/plugin.h @@ -16,13 +16,27 @@ #ifndef _my_plugin_h #define _my_plugin_h - /* On Windows, exports from DLL need to be declared + 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 diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index f9ef76f29ec..61f0458c511 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -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) diff --git a/plugin/fulltext/CMakeLists.txt b/plugin/fulltext/CMakeLists.txt new file mode 100644 index 00000000000..cf696c19e61 --- /dev/null +++ b/plugin/fulltext/CMakeLists.txt @@ -0,0 +1,3 @@ +INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake") +SET(FTEXAMPLE_SOURCES plugin_example.c) +MYSQL_PLUGIN(FTEXAMPLE) diff --git a/storage/maria/CMakeLists.txt b/storage/maria/CMakeLists.txt index 43c43ccb940..ad3a64f9558 100644 --- a/storage/maria/CMakeLists.txt +++ b/storage/maria/CMakeLists.txt @@ -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") diff --git a/storage/maria/unittest/CMakeLists.txt b/storage/maria/unittest/CMakeLists.txt index a6e8736daab..715a6199185 100644 --- a/storage/maria/unittest/CMakeLists.txt +++ b/storage/maria/unittest/CMakeLists.txt @@ -13,10 +13,9 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include ${CMAKE_SOURCE_DIR}/zlib ${CMAKE_SOURCE_DIR}/unittest/mytap) -LINK_LIBRARIES(maria myisam mytap mysys dbug strings wsock32 zlib) +LINK_LIBRARIES(libmaria_s libmyisam_s mytap mysys dbug strings wsock32 zlib) ADD_EXECUTABLE(ma_control_file-t ma_control_file-t.c) ADD_EXECUTABLE(trnman-t trnman-t.c) diff --git a/storage/myisam/CMakeLists.txt b/storage/myisam/CMakeLists.txt index 2d0d1bca7a4..a9c221ff1ff 100644 --- a/storage/myisam/CMakeLists.txt +++ b/storage/myisam/CMakeLists.txt @@ -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") diff --git a/storage/mysql_storage_engine.cmake b/storage/mysql_storage_engine.cmake index 3aba9773202..02acfdf15df 100644 --- a/storage/mysql_storage_engine.cmake +++ b/storage/mysql_storage_engine.cmake @@ -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 .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_.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) diff --git a/storage/xtradb/CMakeLists.txt b/storage/xtradb/CMakeLists.txt index 9782f43fb27..608d6865bf4 100644 --- a/storage/xtradb/CMakeLists.txt +++ b/storage/xtradb/CMakeLists.txt @@ -13,15 +13,9 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -# This is the CMakeLists for InnoDB Plugin +# This is the CMakeLists for XtraDB - - -# Starting at 5.1.38, MySQL CMake files are simplified. But the plugin -# CMakeLists.txt still needs to work with previous versions of MySQL. -IF (MYSQL_VERSION_ID GREATER "50137") - INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake") -ENDIF (MYSQL_VERSION_ID GREATER "50137") +INCLUDE("${PROJECT_SOURCE_DIR}/storage/mysql_storage_engine.cmake") IF (CMAKE_SIZEOF_VOID_P MATCHES 8) SET(WIN64 TRUE) diff --git a/win/README b/win/README index 916f64913ac..8ae611ec746 100644 --- a/win/README +++ b/win/README @@ -51,12 +51,10 @@ win\configure 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= Server suffix, default none COMPILATION_COMMENT= Server comment, default "Source distribution" @@ -70,7 +68,7 @@ The options right now are: So the command line could look like: -win\configure WITH_INNOBASE_STORAGE_ENGINE WITH_PARTITION_STORAGE_ENGINE MYSQL_SERVER_SUFFIX=-pro +win\configure --with-plugin-innobase --with-plugin-partition MYSQL_SERVER_SUFFIX=-pro Step 6 ------ diff --git a/win/configure-mariadb.bat b/win/configure-mariadb.bat index 834d73732b8..158d22c9aca 100644 --- a/win/configure-mariadb.bat +++ b/win/configure-mariadb.bat @@ -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 diff --git a/win/configure-mariadb.sh b/win/configure-mariadb.sh index b3433ee568f..c6324bfd259 100644 --- a/win/configure-mariadb.sh +++ b/win/configure-mariadb.sh @@ -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 - diff --git a/win/configure.js b/win/configure.js index 0b3157a7d2a..04659ef633a 100644 --- a/win/configure.js +++ b/win/configure.js @@ -126,7 +126,7 @@ try var engineOptions = ParsePlugins(); for (option in engineOptions) { - configfile.WriteLine("SET(" + engineOptions[option] + " TRUE)"); + configfile.WriteLine("SET (" + engineOptions[option] + " TRUE)"); } configfile.Close(); @@ -302,7 +302,7 @@ function ParsePlugins() { var content = fso.OpenTextFile(filename, ForReading).ReadAll(); var match = - /MYSQL_STORAGE_ENGINE([ ]*)[\(]([^\)]+)[\)]/.exec(content); + /MYSQL_(PLUGIN|STORAGE_ENGINE)([ ]*)[\(]([^\)]+)[\)]/.exec(content); if (match== null) continue; match = /\[[\w,\-_]+\][\s]?\)/.exec(match[0]); @@ -329,9 +329,9 @@ function ParsePlugins() for(key in config) { var eng = config[key]; - if(eng.isGroup != undefined && !eng.isGroup && eng.include != undefined) + if(eng.isGroup != undefined && !eng.isGroup && eng.include != undefined) { - if (fso.FolderExists("storage\\"+key) || key=="PARTITION") + if (fso.FolderExists("storage\\"+key) || fso.FolderExists("plugin\\"+key) || key=="PARTITION") { arr[arr.length] = eng.include? "WITH_"+key+"_STORAGE_ENGINE":"WITHOUT_"+key+"_STORAGE_ENGINE"; From c0e11db793507543b9c5f1c5be0501b7aa7d42f8 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 4 Oct 2011 15:48:39 +0200 Subject: [PATCH 06/12] fix for static plugins in mariadb. send "startup" message 5 minutes after startup, not immediately Makefile.am: mariadb uses .la libraries for static plugins. mysql - .a libraries plug.in: mariadb uses .la libraries for static plugins. mysql - .a libraries sender_thread.cc: send "startup" message 5 minutes after startup, not immediately url_http.cc: avoid "unused variable https" warning --- Makefile.am | 7 +++---- plug.in | 8 +++++++- sender_thread.cc | 27 +++++++++++++++++---------- url_http.cc | 13 ++++--------- 4 files changed, 31 insertions(+), 24 deletions(-) diff --git a/Makefile.am b/Makefile.am index 0aea977b464..31727ad0d73 100644 --- a/Makefile.am +++ b/Makefile.am @@ -2,16 +2,15 @@ pkgplugindir = $(pkglibdir)/plugin INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include \ -I$(top_srcdir)/regex -I$(top_srcdir)/sql -EXTRA_LTLIBRARIES = feedback.la +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 -EXTRA_LIBRARIES = libfeedback.a -noinst_LIBRARIES = @plugin_feedback_static_target@ -libfeedback_a_SOURCES= feedback.cc utils.cc url_base.cc url_http.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 diff --git a/plug.in b/plug.in index 0c93fef2327..409a35c8f9a 100644 --- a/plug.in +++ b/plug.in @@ -11,7 +11,13 @@ 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]) -MYSQL_PLUGIN_STATIC(feedback, [libfeedback.a]) +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]) + +]) MYSQL_PLUGIN_ACTIONS(feedback, [ AC_CHECK_HEADERS([netdb.h sys/utsname.h]) diff --git a/sender_thread.cc b/sender_thread.cc index 813690b8819..86627add808 100644 --- a/sender_thread.cc +++ b/sender_thread.cc @@ -23,8 +23,9 @@ static my_thread_id thd_thread_id; ///< its thread_id static size_t needed_size= 20480; -static const time_t next_interval= 60*60*24*7; ///< in seconds (one week) +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 @@ -141,7 +142,7 @@ static bool going_down() /** just like sleep, but waits on a condition and checks "plugin shutdown" status */ -static int delay(time_t sec) +static int slept_ok(time_t sec) { struct timespec abstime; int ret= 0; @@ -153,7 +154,7 @@ static int delay(time_t sec) ret= pthread_cond_timedwait(&sleep_condition, &sleep_mutex, &abstime); pthread_mutex_unlock(&sleep_mutex); - return going_down(); + return !going_down(); } /** @@ -241,7 +242,7 @@ static void send_report(const char *when) } if (last_todo < 0) break; - } while (delay(send_retry_wait) == 0); // wait a little bit before retrying + } while (slept_ok(send_retry_wait)); // wait a little bit before retrying ret: if (thd) @@ -269,8 +270,6 @@ ret: */ pthread_handler_t background_thread(void *arg __attribute__((unused))) { - time_t interval; - if (my_thread_init()) return 0; @@ -278,12 +277,20 @@ pthread_handler_t background_thread(void *arg __attribute__((unused))) thd_thread_id= thread_id++; pthread_mutex_unlock(&LOCK_thread_count); - send_report("startup"); + if (slept_ok(startup_interval)) + { + send_report("startup"); - for (interval= first_interval; delay(interval) == 0; interval= next_interval) - send_report(NULL); + if (slept_ok(first_interval)) + { + send_report(NULL); - send_report("shutdown"); + while(slept_ok(interval)) + send_report(NULL); + } + + send_report("shutdown"); + } my_thread_end(); pthread_exit(0); diff --git a/url_http.cc b/url_http.cc index efe987327d3..de2877b0274 100644 --- a/url_http.cc +++ b/url_http.cc @@ -28,11 +28,6 @@ namespace feedback { -static const char *http= "http://"; -static const size_t http_len= 7; -static const char *https= "https://"; -static const size_t https_len= 8; - static const uint FOR_READING= 0; static const uint FOR_WRITING= 1; @@ -88,13 +83,13 @@ Url* http_create(const char *url, size_t url_length) LEX_STRING host, port, path; bool ssl= false; - if (is_prefix(url, http)) - s= url + http_len; + if (is_prefix(url, "http://")) + s= url + 7; #ifdef HAVE_OPENSSL - else if (is_prefix(url, https)) + else if (is_prefix(url, "https://")) { ssl= true; - s= url + https_len; + s= url + 8; } #endif else From 1b7e566683d13906530a2218791bb5f48b6425ec Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Tue, 4 Oct 2011 16:51:39 +0200 Subject: [PATCH 07/12] tests for feedback plugin, bugfix: garbage in PLUGIN_VAR_STR variables when INSTALL'ing a plugin mysql-test/include/default_mysqld.cnf: disable feedback plugin by default. when enabled - tag is as a test run --- mysql-test/include/default_mysqld.cnf | 2 ++ mysql-test/r/feedback_plugin_install.result | 13 +++++++++++ mysql-test/r/feedback_plugin_load.result | 11 ++++++++++ mysql-test/r/feedback_plugin_send.result | 15 +++++++++++++ mysql-test/t/feedback_plugin_install.opt | 1 + mysql-test/t/feedback_plugin_install.test | 14 ++++++++++++ mysql-test/t/feedback_plugin_load.opt | 2 ++ mysql-test/t/feedback_plugin_load.test | 9 ++++++++ mysql-test/t/feedback_plugin_send.test | 24 +++++++++++++++++++++ sql/sql_plugin.cc | 13 +++++++++++ 10 files changed, 104 insertions(+) create mode 100644 mysql-test/r/feedback_plugin_install.result create mode 100644 mysql-test/r/feedback_plugin_load.result create mode 100644 mysql-test/r/feedback_plugin_send.result create mode 100644 mysql-test/t/feedback_plugin_install.opt create mode 100644 mysql-test/t/feedback_plugin_install.test create mode 100644 mysql-test/t/feedback_plugin_load.opt create mode 100644 mysql-test/t/feedback_plugin_load.test create mode 100644 mysql-test/t/feedback_plugin_send.test diff --git a/mysql-test/include/default_mysqld.cnf b/mysql-test/include/default_mysqld.cnf index e46c3bc3c17..a1b477c51dd 100644 --- a/mysql-test/include/default_mysqld.cnf +++ b/mysql-test/include/default_mysqld.cnf @@ -15,6 +15,8 @@ max_heap_table_size= 1M loose-skip-innodb loose-skip-pbxt +loose-skip-feedback +loose-feedback-user-info= mysql-test loose-innodb_data_file_path= ibdata1:10M:autoextend diff --git a/mysql-test/r/feedback_plugin_install.result b/mysql-test/r/feedback_plugin_install.result new file mode 100644 index 00000000000..e017276b619 --- /dev/null +++ b/mysql-test/r/feedback_plugin_install.result @@ -0,0 +1,13 @@ +install plugin feedback soname 'feedback.so'; +select plugin_status from information_schema.plugins where plugin_name='feedback'; +plugin_status +ACTIVE +select * from information_schema.feedback where variable_name like 'feed%' + and variable_name not like '%_uid'; +VARIABLE_NAME VARIABLE_VALUE +FEEDBACK_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; diff --git a/mysql-test/r/feedback_plugin_load.result b/mysql-test/r/feedback_plugin_load.result new file mode 100644 index 00000000000..f097c5d9a9d --- /dev/null +++ b/mysql-test/r/feedback_plugin_load.result @@ -0,0 +1,11 @@ +select plugin_status from information_schema.plugins where plugin_name='feedback'; +plugin_status +ACTIVE +select * from information_schema.feedback where variable_name like 'feed%' + and variable_name not like '%_uid'; +VARIABLE_NAME VARIABLE_VALUE +FEEDBACK_SEND_RETRY_WAIT 60 +FEEDBACK_USER_INFO mysql-test +FEEDBACK_SEND_TIMEOUT 60 +FEEDBACK_URL http://mariadb.org/feedback_plugin/post +FEEDBACK 1.0 diff --git a/mysql-test/r/feedback_plugin_send.result b/mysql-test/r/feedback_plugin_send.result new file mode 100644 index 00000000000..e7d3238146b --- /dev/null +++ b/mysql-test/r/feedback_plugin_send.result @@ -0,0 +1,15 @@ +select plugin_status from information_schema.plugins where plugin_name='feedback'; +plugin_status +ACTIVE +select * from information_schema.feedback where variable_name like 'feed%' + and variable_name not like '%_uid'; +VARIABLE_NAME VARIABLE_VALUE +FEEDBACK_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' diff --git a/mysql-test/t/feedback_plugin_install.opt b/mysql-test/t/feedback_plugin_install.opt new file mode 100644 index 00000000000..a711ae94e69 --- /dev/null +++ b/mysql-test/t/feedback_plugin_install.opt @@ -0,0 +1 @@ +--loose-feedback diff --git a/mysql-test/t/feedback_plugin_install.test b/mysql-test/t/feedback_plugin_install.test new file mode 100644 index 00000000000..f2bbe0b9e58 --- /dev/null +++ b/mysql-test/t/feedback_plugin_install.test @@ -0,0 +1,14 @@ +--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; + diff --git a/mysql-test/t/feedback_plugin_load.opt b/mysql-test/t/feedback_plugin_load.opt new file mode 100644 index 00000000000..5fbb2f83954 --- /dev/null +++ b/mysql-test/t/feedback_plugin_load.opt @@ -0,0 +1,2 @@ +--loose-feedback +--plugin-load=$FEEDBACK_SO diff --git a/mysql-test/t/feedback_plugin_load.test b/mysql-test/t/feedback_plugin_load.test new file mode 100644 index 00000000000..a395052dafe --- /dev/null +++ b/mysql-test/t/feedback_plugin_load.test @@ -0,0 +1,9 @@ +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'; diff --git a/mysql-test/t/feedback_plugin_send.test b/mysql-test/t/feedback_plugin_send.test new file mode 100644 index 00000000000..b49c0d0e252 --- /dev/null +++ b/mysql-test/t/feedback_plugin_send.test @@ -0,0 +1,24 @@ +source t/feedback_plugin_load.test; +source include/big_test.inc; + +if (!$MTR_FEEDBACK_PLUGIN) { + skip MTR_FEEDBACK_PLUGIN is not set; +} + +# +# Yep. The plugin waits 5 minutes before sending anything, +# and there's no way to force it to send anything sooner. +# Let's wait, and hope that mtr is started with --parallel and +# is doing some work in other workers. +# +sleep 310; +source include/restart_mysqld.inc; + +replace_result https http; +perl; + $log_error= $ENV{'MYSQLTEST_VARDIR'} . '/log/mysqld.1.err'; + open(LOG, '<', $log_error) or die "open(< $log_error): $!"; + /feedback plugin:.*/ && print "$&\n" while $_=; + close LOG; +EOF + diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc index dbbcd7e8c86..8fc02f4b196 100644 --- a/sql/sql_plugin.cc +++ b/sql/sql_plugin.cc @@ -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) From da81a1f01e2b689c61d549e1277ac0c2d61c2814 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Wed, 5 Oct 2011 20:16:42 +0200 Subject: [PATCH 08/12] fix fulltext_plugin.test on windows --- mysql-test/t/fulltext_plugin.test | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/fulltext_plugin.test b/mysql-test/t/fulltext_plugin.test index 31978dadc51..0e2f53d5b15 100644 --- a/mysql-test/t/fulltext_plugin.test +++ b/mysql-test/t/fulltext_plugin.test @@ -3,7 +3,8 @@ # # BUG#39746 - Debug flag breaks struct definition (server crash) # -INSTALL PLUGIN simple_parser SONAME 'mypluglib.so'; +--replace_result .dll .so +eval INSTALL PLUGIN simple_parser SONAME '$MYPLUGLIB_SO'; CREATE TABLE t1(a TEXT, b TEXT, FULLTEXT(a) WITH PARSER simple_parser); ALTER TABLE t1 ADD FULLTEXT(b) WITH PARSER simple_parser; DROP TABLE t1; From 033a2527da96e80f2a46a5ede84d3e03544c51e0 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 6 Oct 2011 18:24:00 +0200 Subject: [PATCH 09/12] add #define WITH_FEEDBACK_PLUGIN --- plug.in | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plug.in b/plug.in index 409a35c8f9a..88a4448321d 100644 --- a/plug.in +++ b/plug.in @@ -19,6 +19,9 @@ 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]) ]) From c9783670c7b2aecef3417e100f6eaad7924a2133 Mon Sep 17 00:00:00 2001 From: Vladislav Vaintroub Date: Thu, 6 Oct 2011 20:55:38 +0200 Subject: [PATCH 10/12] Implement uname() on Windows. Also, fix code to get physical memory size. --- plugin/feedback/utils.cc | 90 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/plugin/feedback/utils.cc b/plugin/feedback/utils.cc index f5afd427ebf..db19e9ae9b4 100644 --- a/plugin/feedback/utils.cc +++ b/plugin/feedback/utils.cc @@ -22,8 +22,90 @@ #include #include -#ifdef HAVE_SYS_UTSNAME_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 +#endif + +#ifdef HAVE_SYS_UTSNAME_H static bool have_ubuf= false; static struct utsname ubuf; #endif @@ -110,6 +192,12 @@ static ulonglong my_getphysmem() #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 From e513652a4ec71daa33cfc96b0c167312711b3b0f Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 6 Oct 2011 23:39:44 +0200 Subject: [PATCH 11/12] disable feedback plugin by default. Now on windows too. --- sql/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 5856b795ba8..103074d1747 100755 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -35,7 +35,9 @@ SET_SOURCE_FILES_PROPERTIES(${CMAKE_SOURCE_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 From 4a4aa358f39c85fef7486a857abde11615544f71 Mon Sep 17 00:00:00 2001 From: Sergei Golubchik Date: Thu, 6 Oct 2011 23:40:19 +0200 Subject: [PATCH 12/12] sort results in tests to make them stable --- mysql-test/r/feedback_plugin_install.result | 4 ++-- mysql-test/r/feedback_plugin_load.result | 4 ++-- mysql-test/r/feedback_plugin_send.result | 4 ++-- mysql-test/t/feedback_plugin_install.test | 1 + mysql-test/t/feedback_plugin_load.test | 1 + 5 files changed, 8 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/feedback_plugin_install.result b/mysql-test/r/feedback_plugin_install.result index e017276b619..4b3b0226fae 100644 --- a/mysql-test/r/feedback_plugin_install.result +++ b/mysql-test/r/feedback_plugin_install.result @@ -5,9 +5,9 @@ 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_USER_INFO mysql-test FEEDBACK_SEND_TIMEOUT 60 FEEDBACK_URL http://mariadb.org/feedback_plugin/post -FEEDBACK 1.0 +FEEDBACK_USER_INFO mysql-test uninstall plugin feedback; diff --git a/mysql-test/r/feedback_plugin_load.result b/mysql-test/r/feedback_plugin_load.result index f097c5d9a9d..bc02b920a11 100644 --- a/mysql-test/r/feedback_plugin_load.result +++ b/mysql-test/r/feedback_plugin_load.result @@ -4,8 +4,8 @@ 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_USER_INFO mysql-test FEEDBACK_SEND_TIMEOUT 60 FEEDBACK_URL http://mariadb.org/feedback_plugin/post -FEEDBACK 1.0 +FEEDBACK_USER_INFO mysql-test diff --git a/mysql-test/r/feedback_plugin_send.result b/mysql-test/r/feedback_plugin_send.result index e7d3238146b..22379e26248 100644 --- a/mysql-test/r/feedback_plugin_send.result +++ b/mysql-test/r/feedback_plugin_send.result @@ -4,11 +4,11 @@ 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_USER_INFO mysql-test FEEDBACK_SEND_TIMEOUT 60 FEEDBACK_URL http://mariadb.org/feedback_plugin/post -FEEDBACK 1.0 +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 diff --git a/mysql-test/t/feedback_plugin_install.test b/mysql-test/t/feedback_plugin_install.test index f2bbe0b9e58..81343c436c3 100644 --- a/mysql-test/t/feedback_plugin_install.test +++ b/mysql-test/t/feedback_plugin_install.test @@ -8,6 +8,7 @@ if (`select length('$FEEDBACK_SO') = 0`) { eval install plugin feedback soname '$FEEDBACK_SO'; select plugin_status from information_schema.plugins where plugin_name='feedback'; --replace_result https http +--sorted_result select * from information_schema.feedback where variable_name like 'feed%' and variable_name not like '%_uid'; uninstall plugin feedback; diff --git a/mysql-test/t/feedback_plugin_load.test b/mysql-test/t/feedback_plugin_load.test index a395052dafe..5ad301667b4 100644 --- a/mysql-test/t/feedback_plugin_load.test +++ b/mysql-test/t/feedback_plugin_load.test @@ -5,5 +5,6 @@ if (`select count(*) = 0 from information_schema.plugins where plugin_name = 'fe 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';