mirror of
				https://github.com/MariaDB/server.git
				synced 2025-10-31 19:06:14 +01:00 
			
		
		
		
	 ba01c2aaf0
			
		
	
	
	ba01c2aaf0
	
	
	
		
			
			* rpl.rpl_system_versioning_partitions updated for MDEV-32188 * innodb.row_size_error_log_warnings_3 changed error for MDEV-33658 (checks are done in a different order)
		
			
				
	
	
		
			428 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			428 lines
		
	
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 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 {
 | |
| 
 | |
| #ifndef DBUG_OFF
 | |
| ulong debug_startup_interval, debug_first_interval, debug_interval;
 | |
| #endif
 | |
| 
 | |
| /* backing store for system variables */
 | |
| static char *url, *http_proxy;
 | |
| char *user_info, *server_uid_ptr= server_uid;
 | |
| ulong send_timeout, send_retry_wait;
 | |
| 
 | |
| /**
 | |
|   these three are used to communicate the shutdown signal to the
 | |
|   background thread
 | |
| */
 | |
| mysql_mutex_t sleep_mutex;
 | |
| mysql_cond_t sleep_condition;
 | |
| volatile bool shutdown_plugin;
 | |
| static pthread_t sender_thread;
 | |
| 
 | |
| #ifdef HAVE_PSI_INTERFACE
 | |
| static PSI_mutex_key key_sleep_mutex;
 | |
| static PSI_mutex_info mutex_list[]=
 | |
| {{ &key_sleep_mutex, "sleep_mutex", PSI_FLAG_GLOBAL}};
 | |
| 
 | |
| static PSI_cond_key key_sleep_cond;
 | |
| static PSI_cond_info cond_list[]=
 | |
| {{ &key_sleep_cond, "sleep_condition", PSI_FLAG_GLOBAL}};
 | |
| 
 | |
| static PSI_thread_key key_sender_thread;
 | |
| static PSI_thread_info	thread_list[] =
 | |
| {{&key_sender_thread, "sender_thread", 0}};
 | |
| #endif
 | |
| 
 | |
| 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[] =
 | |
| {
 | |
|   Show::Column("VARIABLE_NAME",  Show::Varchar(255),  NOT_NULL),
 | |
|   Show::Column("VARIABLE_VALUE", Show::Varchar(1024), NOT_NULL),
 | |
|   Show::CEnd()
 | |
| };
 | |
| 
 | |
| 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;
 | |
|   /* A reference to this context will be stored in Item_field */
 | |
|   Name_resolution_context *nrc= new (thd->mem_root) Name_resolution_context;
 | |
|   LEX_CSTRING &db= tables->db;
 | |
|   LEX_CSTRING &table= tables->alias;
 | |
|   LEX_CSTRING &field= tables->table->field[0]->field_name;
 | |
|   CHARSET_INFO *cs= &my_charset_latin1;
 | |
| 
 | |
|   if (!filter->str || !nrc)
 | |
|     return 0;
 | |
| 
 | |
|   nrc->resolve_in_table_list_only(tables);
 | |
|   nrc->select_lex= tables->select_lex;
 | |
| 
 | |
|   res= new (thd->mem_root) Item_cond_or(thd);
 | |
|   if (!res)
 | |
|     return OOM;
 | |
| 
 | |
|   for (; filter->str; filter++)
 | |
|   {
 | |
|     Item_field  *fld= new (thd->mem_root) Item_field(thd, nrc, db, table,
 | |
|                                                      field);
 | |
|     Item_string *pattern= new (thd->mem_root) Item_string(thd, filter->str,
 | |
|                                                           (uint) filter->length, cs);
 | |
|     Item_string *escape= new (thd->mem_root) Item_string(thd, "\\", 1, cs);
 | |
| 
 | |
|     if (!fld || !pattern || !escape)
 | |
|       return OOM;
 | |
| 
 | |
|     Item_func_like *like= new (thd->mem_root) Item_func_like(thd, fld, pattern,
 | |
|                                                              escape, 0);
 | |
| 
 | |
|     if (!like)
 | |
|       return OOM;
 | |
| 
 | |
|     res->add(like, thd->mem_root);
 | |
|   }
 | |
| 
 | |
|   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("innodb_f%")},
 | |
|   {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("default_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("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)
 | |
|            || fill_collation_statistics(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
 | |
| 
 | |
| #ifdef HAVE_PSI_INTERFACE
 | |
| #define PSI_register(X) \
 | |
|   if(PSI_server) PSI_server->register_ ## X("feedback", X ## _list, array_elements(X ## _list))
 | |
| #else
 | |
| #define PSI_register(X) /* no-op */
 | |
| #endif
 | |
| 
 | |
|   PSI_register(mutex);
 | |
|   PSI_register(cond);
 | |
|   PSI_register(thread);
 | |
| 
 | |
|   prepare_linux_info();
 | |
| 
 | |
| #ifndef DBUG_OFF
 | |
|   if (startup_interval != debug_startup_interval ||
 | |
|       first_interval != debug_first_interval ||
 | |
|       interval != debug_interval)
 | |
|   {
 | |
|     startup_interval= debug_startup_interval;
 | |
|     first_interval= debug_first_interval;
 | |
|     interval= debug_interval;
 | |
|     user_info= const_cast<char*>("mysql-test");
 | |
|   }
 | |
| #endif
 | |
| 
 | |
|   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(PSI_INSTRUMENT_ME, 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)))
 | |
|         {
 | |
|           if (urls[slot]->set_proxy(http_proxy,
 | |
|                                     http_proxy ? strlen(http_proxy) : 0))
 | |
|             sql_print_error("feedback plugin: invalid proxy '%s'",
 | |
|                             http_proxy ? http_proxy : "");
 | |
|           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)
 | |
|     {
 | |
|       mysql_mutex_init(0, &sleep_mutex, 0);
 | |
|       mysql_cond_init(0, &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);
 | |
|   }
 | |
| 
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| /**
 | |
|    plugin deinitialization function
 | |
| */
 | |
| static int free(void *p)
 | |
| {
 | |
|   if (url_count)
 | |
|   {
 | |
|     mysql_mutex_lock(&sleep_mutex);
 | |
|     shutdown_plugin= true;
 | |
|     mysql_cond_signal(&sleep_condition);
 | |
|     mysql_mutex_unlock(&sleep_mutex);
 | |
| 
 | |
|     for (uint i= 0; i < url_count; i++)
 | |
|       urls[i]->abort();
 | |
| 
 | |
|     pthread_join(sender_thread, NULL);
 | |
| 
 | |
|     mysql_mutex_destroy(&sleep_mutex);
 | |
|     mysql_cond_destroy(&sleep_condition);
 | |
| 
 | |
|     for (uint i= 0; i < url_count; i++)
 | |
|       delete urls[i];
 | |
|     my_free(urls);
 | |
|   }
 | |
|   return 0;
 | |
| }
 | |
| 
 | |
| #ifdef HAVE_OPENSSL
 | |
| #define DEFAULT_PROTO "https://"
 | |
| #else
 | |
| #define DEFAULT_PROTO "http://"
 | |
| #endif
 | |
| 
 | |
| static MYSQL_SYSVAR_STR(server_uid, server_uid_ptr,
 | |
|        PLUGIN_VAR_READONLY | PLUGIN_VAR_NOCMDOPT,
 | |
|        "Automatically calculated server unique id hash", NULL, NULL, 0);
 | |
| static MYSQL_SYSVAR_STR(user_info, user_info,
 | |
|        PLUGIN_VAR_READONLY | PLUGIN_VAR_RQCMDARG,
 | |
|        "User specified string that will be included in the feedback report",
 | |
|        NULL, NULL, "");
 | |
| static MYSQL_SYSVAR_STR(url, url, PLUGIN_VAR_READONLY | PLUGIN_VAR_RQCMDARG,
 | |
|        "Space separated URLs to send the feedback report to", NULL, NULL,
 | |
|        DEFAULT_PROTO "feedback.mariadb.org/rest/v1/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 MYSQL_SYSVAR_STR(http_proxy, http_proxy,
 | |
|                         PLUGIN_VAR_READONLY | PLUGIN_VAR_RQCMDARG,
 | |
|        "Proxy server host:port", NULL, NULL,0);
 | |
| 
 | |
| #ifndef DBUG_OFF
 | |
| static MYSQL_SYSVAR_ULONG(debug_startup_interval, debug_startup_interval,
 | |
|        PLUGIN_VAR_RQCMDARG, "for debugging only",
 | |
|        NULL, NULL, startup_interval, 1, INT_MAX32, 1);
 | |
| static MYSQL_SYSVAR_ULONG(debug_first_interval, debug_first_interval,
 | |
|        PLUGIN_VAR_RQCMDARG, "for debugging only",
 | |
|        NULL, NULL, first_interval, 1, INT_MAX32, 1);
 | |
| static MYSQL_SYSVAR_ULONG(debug_interval, debug_interval,
 | |
|        PLUGIN_VAR_RQCMDARG, "for debugging only",
 | |
|        NULL, NULL, interval, 1, INT_MAX32, 1);
 | |
| #endif
 | |
| 
 | |
| 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),
 | |
|   MYSQL_SYSVAR(http_proxy),
 | |
| #ifndef DBUG_OFF
 | |
|   MYSQL_SYSVAR(debug_startup_interval),
 | |
|   MYSQL_SYSVAR(debug_first_interval),
 | |
|   MYSQL_SYSVAR(debug_interval),
 | |
| #endif
 | |
|   NULL
 | |
| };
 | |
| 
 | |
| 
 | |
| static struct st_mysql_information_schema feedback =
 | |
| { MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION };
 | |
| 
 | |
| } // namespace feedback
 | |
| 
 | |
| maria_declare_plugin(feedback)
 | |
| {
 | |
|   MYSQL_INFORMATION_SCHEMA_PLUGIN,
 | |
|   &feedback::feedback,
 | |
|   "FEEDBACK",
 | |
|   "Sergei Golubchik",
 | |
|   "MariaDB User Feedback Plugin",
 | |
|   PLUGIN_LICENSE_GPL,
 | |
|   feedback::init,
 | |
|   feedback::free,
 | |
|   0x0101,
 | |
|   NULL,
 | |
|   feedback::settings,
 | |
|   "1.1",
 | |
|   MariaDB_PLUGIN_MATURITY_STABLE
 | |
| }
 | |
| maria_declare_plugin_end;
 |