diff options
Diffstat (limited to 'sql/set_var.cc')
-rw-r--r-- | sql/set_var.cc | 241 |
1 files changed, 238 insertions, 3 deletions
diff --git a/sql/set_var.cc b/sql/set_var.cc index a44395c74ca..e6b0625f097 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -55,6 +55,7 @@ #include <my_getopt.h> #include <thr_alarm.h> #include <myisam.h> +#include <my_dir.h> #include "event_scheduler.h" @@ -164,6 +165,11 @@ static byte *get_error_count(THD *thd); static byte *get_warning_count(THD *thd); static byte *get_prepared_stmt_count(THD *thd); static byte *get_tmpdir(THD *thd); +static int sys_check_log_path(THD *thd, set_var *var); +static bool sys_update_general_log_path(THD *thd, set_var * var); +static void sys_default_general_log_path(THD *thd, enum_var_type type); +static bool sys_update_slow_log_path(THD *thd, set_var * var); +static void sys_default_slow_log_path(THD *thd, enum_var_type type); /* Variable definition list @@ -681,6 +687,22 @@ sys_var_have_variable sys_have_row_based_replication("have_row_based_replication /* Global read-only variable describing server license */ sys_var_const_str sys_license("license", STRINGIFY_ARG(LICENSE)); +/* Global variables which enable|disable logging */ +sys_var_log_state sys_var_general_log("general_log", &opt_log, + QUERY_LOG_GENERAL); +sys_var_log_state sys_var_slow_query_log("slow_query_log", &opt_slow_log, + QUERY_LOG_SLOW); +sys_var_str sys_var_general_log_path("general_log_file", sys_check_log_path, + sys_update_general_log_path, + sys_default_general_log_path, + opt_logname); +sys_var_str sys_var_slow_log_path("slow_query_log_file", sys_check_log_path, + sys_update_slow_log_path, + sys_default_slow_log_path, + opt_slow_logname); +sys_var_log_output sys_var_log_output_state("log_output", &log_output_options, + &log_output_typelib, 0); + #ifdef HAVE_REPLICATION static int show_slave_skip_errors(THD *thd, SHOW_VAR *var, char *buff) { @@ -779,6 +801,8 @@ SHOW_VAR init_vars[]= { {"ft_min_word_len", (char*) &ft_min_word_len, SHOW_LONG}, {"ft_query_expansion_limit",(char*) &ft_query_expansion_limit, SHOW_LONG}, {"ft_stopword_file", (char*) &ft_stopword_file, SHOW_CHAR_PTR}, + {sys_var_general_log.name, (char*) &opt_log, SHOW_MY_BOOL}, + {sys_var_general_log_path.name, (char*) &sys_var_general_log_path, SHOW_SYS}, {sys_group_concat_max_len.name, (char*) &sys_group_concat_max_len, SHOW_SYS}, {sys_have_archive_db.name, (char*) &have_archive_db, SHOW_HAVE}, {sys_have_berkeley_db.name, (char*) &have_berkeley_db, SHOW_HAVE}, @@ -856,6 +880,7 @@ SHOW_VAR init_vars[]= { {"log_bin", (char*) &opt_bin_log, SHOW_BOOL}, {sys_trust_function_creators.name,(char*) &sys_trust_function_creators, SHOW_SYS}, {"log_error", (char*) log_error_file, SHOW_CHAR}, + {sys_var_log_output_state.name, (char*) &sys_var_log_output_state, SHOW_SYS}, {sys_log_queries_not_using_indexes.name, (char*) &sys_log_queries_not_using_indexes, SHOW_SYS}, #ifdef HAVE_REPLICATION @@ -981,6 +1006,8 @@ SHOW_VAR init_vars[]= { {sys_slave_trans_retries.name,(char*) &sys_slave_trans_retries, SHOW_SYS}, #endif {sys_slow_launch_time.name, (char*) &sys_slow_launch_time, SHOW_SYS}, + {sys_var_slow_query_log.name, (char*) &opt_slow_log, SHOW_MY_BOOL}, + {sys_var_slow_log_path.name, (char*) &sys_var_slow_log_path, SHOW_SYS}, #ifdef HAVE_SYS_UN_H {"socket", (char*) &mysqld_unix_port, SHOW_CHAR_PTR}, #endif @@ -1301,15 +1328,20 @@ bool sys_var_thd_binlog_format::is_readonly() const if global or not here. And this test will also prevent switching from RBR to RBR (a no-op which should not happen too often). + + If we don't have row-based replication compiled in, the variable + is always read-only. */ -#ifdef HAVE_ROW_BASED_REPLICATION +#ifndef HAVE_ROW_BASED_REPLICATION + my_error(ER_RBR_NOT_AVAILABLE, MYF(0)); + return 1; +#else if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW) && thd->temporary_tables) { my_error(ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR, MYF(0)); return 1; } -#endif /*HAVE_ROW_BASED_REPLICATION*/ /* if in a stored function, it's too late to change mode */ @@ -1327,10 +1359,12 @@ bool sys_var_thd_binlog_format::is_readonly() const my_error(ER_NDB_CANT_SWITCH_BINLOG_FORMAT, MYF(0)); return 1; } -#endif +#endif /* HAVE_NDB_BINLOG */ +#endif /* HAVE_ROW_BASED_REPLICATION */ return sys_var_thd_enum::is_readonly(); } + void fix_binlog_format_after_update(THD *thd, enum_var_type type) { #ifdef HAVE_ROW_BASED_REPLICATION @@ -1338,6 +1372,7 @@ void fix_binlog_format_after_update(THD *thd, enum_var_type type) #endif /*HAVE_ROW_BASED_REPLICATION*/ } + static void fix_max_binlog_size(THD *thd, enum_var_type type) { DBUG_ENTER("fix_max_binlog_size"); @@ -2513,6 +2548,206 @@ end: } +bool sys_var_log_state::update(THD *thd, set_var *var) +{ + bool res= 0; + pthread_mutex_lock(&LOCK_global_system_variables); + if (!var->save_result.ulong_value) + logger.deactivate_log_handler(thd, log_type); + else + { + if ((res= logger.activate_log_handler(thd, log_type))) + { + my_error(ER_CANT_ACTIVATE_LOG, MYF(0), + log_type == QUERY_LOG_GENERAL ? "general" : + "slow query"); + goto err; + } + } +err: + pthread_mutex_unlock(&LOCK_global_system_variables); + return res; +} + +void sys_var_log_state::set_default(THD *thd, enum_var_type type) +{ + pthread_mutex_lock(&LOCK_global_system_variables); + logger.deactivate_log_handler(thd, log_type); + pthread_mutex_unlock(&LOCK_global_system_variables); +} + + +static int sys_check_log_path(THD *thd, set_var *var) +{ + char path[FN_REFLEN]; + MY_STAT f_stat; + const char *var_path= var->value->str_value.ptr(); + bzero(&f_stat, sizeof(MY_STAT)); + + (void) unpack_filename(path, var_path); + if (my_stat(path, &f_stat, MYF(0))) + { + /* Check if argument is a file and we have 'write' permission */ + if (!MY_S_ISREG(f_stat.st_mode) || + !(f_stat.st_mode & MY_S_IWRITE)) + return -1; + } + else + { + /* + Check if directory exists and + we have permission to create file & write to file + */ + (void) dirname_part(path, var_path); + if (my_access(path, (F_OK|W_OK))) + return -1; + } + return 0; +} + + +bool update_sys_var_str_path(THD *thd, sys_var_str *var_str, + set_var *var, const char *log_ext, + bool log_state, uint log_type) +{ + MYSQL_QUERY_LOG *file_log; + char buff[FN_REFLEN]; + char *res= 0, *old_value=(char *)(var ? var->value->str_value.ptr() : 0); + bool result= 0; + uint str_length= (var ? var->value->str_value.length() : 0); + + switch (log_type) { + case QUERY_LOG_SLOW: + file_log= logger.get_slow_log_file_handler(); + break; + case QUERY_LOG_GENERAL: + file_log= logger.get_log_file_handler(); + break; + default: + DBUG_ASSERT(0); + } + + if (!old_value) + { + old_value= make_default_log_name(buff, log_ext); + str_length= strlen(old_value); + } + if (!(res= my_strndup((byte*)old_value, str_length, MYF(MY_FAE+MY_WME)))) + { + result= 1; + goto err; + } + + pthread_mutex_lock(&LOCK_global_system_variables); + logger.lock(); + + if (file_log && log_state) + file_log->close(0); + old_value= var_str->value; + var_str->value= res; + var_str->value_length= str_length; + my_free(old_value, MYF(MY_ALLOW_ZERO_PTR)); + if (file_log && log_state) + { + switch (log_type) { + case QUERY_LOG_SLOW: + file_log->open_slow_log(sys_var_general_log_path.value); + break; + case QUERY_LOG_GENERAL: + file_log->open_query_log(sys_var_general_log_path.value); + break; + default: + DBUG_ASSERT(0); + } + } + + logger.unlock(); + pthread_mutex_unlock(&LOCK_global_system_variables); + +err: + return result; +} + + +static bool sys_update_general_log_path(THD *thd, set_var * var) +{ + return update_sys_var_str_path(thd, &sys_var_general_log_path, + var, ".log", opt_log, QUERY_LOG_GENERAL); +} + + +static void sys_default_general_log_path(THD *thd, enum_var_type type) +{ + (void) update_sys_var_str_path(thd, &sys_var_general_log_path, + 0, ".log", opt_log, QUERY_LOG_GENERAL); +} + + +static bool sys_update_slow_log_path(THD *thd, set_var * var) +{ + return update_sys_var_str_path(thd, &sys_var_slow_log_path, + var, "-slow.log", opt_slow_log, + QUERY_LOG_SLOW); +} + + +static void sys_default_slow_log_path(THD *thd, enum_var_type type) +{ + (void) update_sys_var_str_path(thd, &sys_var_slow_log_path, + 0, "-slow.log", opt_slow_log, + QUERY_LOG_SLOW); +} + + +bool sys_var_log_output::update(THD *thd, set_var *var) +{ + pthread_mutex_lock(&LOCK_global_system_variables); + logger.lock(); + logger.init_slow_log(var->save_result.ulong_value); + logger.init_general_log(var->save_result.ulong_value); + *value= var->save_result.ulong_value; + logger.unlock(); + pthread_mutex_unlock(&LOCK_global_system_variables); + return 0; +} + + +void sys_var_log_output::set_default(THD *thd, enum_var_type type) +{ + pthread_mutex_lock(&LOCK_global_system_variables); + logger.lock(); + logger.init_slow_log(LOG_TABLE); + logger.init_general_log(LOG_TABLE); + *value= LOG_TABLE; + logger.unlock(); + pthread_mutex_unlock(&LOCK_global_system_variables); +} + + +byte *sys_var_log_output::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base) +{ + char buff[256]; + String tmp(buff, sizeof(buff), &my_charset_latin1); + ulong length; + ulong val= *value; + + tmp.length(0); + for (uint i= 0; val; val>>= 1, i++) + { + if (val & 1) + { + tmp.append(log_output_typelib.type_names[i], + log_output_typelib.type_lengths[i]); + tmp.append(','); + } + } + + if ((length= tmp.length())) + length--; + return (byte*) thd->strmake(tmp.ptr(), length); +} + + /***************************************************************************** Functions to handle SET NAMES and SET CHARACTER SET *****************************************************************************/ |