diff options
Diffstat (limited to 'sql/log.cc')
-rw-r--r-- | sql/log.cc | 732 |
1 files changed, 297 insertions, 435 deletions
diff --git a/sql/log.cc b/sql/log.cc index 0bf77d68410..af039c15ffc 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -57,6 +57,35 @@ static int binlog_commit(handlerton *hton, THD *thd, bool all); static int binlog_rollback(handlerton *hton, THD *thd, bool all); static int binlog_prepare(handlerton *hton, THD *thd, bool all); +/** + Silence all errors and warnings reported when performing a write + to a log table. + Errors and warnings are not reported to the client or SQL exception + handlers, so that the presence of logging does not interfere and affect + the logic of an application. +*/ +class Silence_log_table_errors : public Internal_error_handler +{ +public: + Silence_log_table_errors() + {} + + virtual ~Silence_log_table_errors() {} + + virtual bool handle_error(uint sql_errno, + MYSQL_ERROR::enum_warning_level level, + THD *thd); +}; + +bool +Silence_log_table_errors::handle_error(uint /* sql_errno */, + MYSQL_ERROR::enum_warning_level /* level */, + THD * /* thd */) +{ + return TRUE; +} + + sql_print_message_func sql_print_message_handlers[3] = { sql_print_information, @@ -187,6 +216,19 @@ public: handlerton *binlog_hton; +bool LOGGER::is_log_table_enabled(uint log_table_type) +{ + switch (log_table_type) { + case QUERY_LOG_SLOW: + return (table_log_handler != NULL) && opt_slow_log; + case QUERY_LOG_GENERAL: + return (table_log_handler != NULL) && opt_log ; + default: + DBUG_ASSERT(0); + return FALSE; /* make compiler happy */ + } +} + /* Check if a given table is opened log table */ int check_if_log_table(uint db_len, const char *db, uint table_name_len, @@ -200,211 +242,38 @@ int check_if_log_table(uint db_len, const char *db, uint table_name_len, if (table_name_len == 11 && !(lower_case_table_names ? my_strcasecmp(system_charset_info, table_name, "general_log") : - strcmp(table_name, "general_log")) && - (!check_if_opened || logger.is_log_table_enabled(QUERY_LOG_GENERAL))) - return QUERY_LOG_GENERAL; - else - if (table_name_len == 8 && !(lower_case_table_names ? - my_strcasecmp(system_charset_info, table_name, "slow_log") : - strcmp(table_name, "slow_log")) && - (!check_if_opened ||logger.is_log_table_enabled(QUERY_LOG_SLOW))) + strcmp(table_name, "general_log"))) + { + if (!check_if_opened || logger.is_log_table_enabled(QUERY_LOG_GENERAL)) + return QUERY_LOG_GENERAL; + return 0; + } + + if (table_name_len == 8 && !(lower_case_table_names ? + my_strcasecmp(system_charset_info, table_name, "slow_log") : + strcmp(table_name, "slow_log"))) + { + if (!check_if_opened || logger.is_log_table_enabled(QUERY_LOG_SLOW)) return QUERY_LOG_SLOW; + return 0; + } } return 0; } -/* - Open log table of a given type (general or slow log) - - SYNOPSIS - open_log_table() - - log_table_type type of the log table to open: QUERY_LOG_GENERAL - or QUERY_LOG_SLOW - - DESCRIPTION - - The function opens a log table and marks it as such. Log tables are open - during the whole time, while server is running. Except for the moments - when they have to be reopened: during FLUSH LOGS and TRUNCATE. This - function is invoked directly only once during startup. All subsequent - calls happen through reopen_log_table(), which performs additional check. - - RETURN - FALSE - OK - TRUE - error occured -*/ - -bool Log_to_csv_event_handler::open_log_table(uint log_table_type) -{ - THD *log_thd, *curr= current_thd; - TABLE_LIST *table; - bool error= FALSE; - DBUG_ENTER("open_log_table"); - - switch (log_table_type) { - case QUERY_LOG_GENERAL: - log_thd= general_log_thd; - table= &general_log; - /* clean up table before reuse/initial usage */ - bzero((char*) table, sizeof(TABLE_LIST)); - table->alias= table->table_name= (char*) "general_log"; - table->table_name_length= 11; - break; - case QUERY_LOG_SLOW: - log_thd= slow_log_thd; - table= &slow_log; - bzero((char*) table, sizeof(TABLE_LIST)); - table->alias= table->table_name= (char*) "slow_log"; - table->table_name_length= 8; - break; - default: - assert(0); // Impossible - } - - /* - This way we check that appropriate log thd was created ok during - initialization. We cannot check "is_log_tables_initialized" var, as - the very initialization is not finished until this function is - completed in the very first time. - */ - if (!log_thd) - { - DBUG_PRINT("error",("Cannot initialize log tables")); - DBUG_RETURN(TRUE); - } - - /* - Set THD's thread_stack. This is needed to perform stack overrun - check, which is done by some routines (e.g. open_table()). - In the case we are called by thread, which already has this parameter - set, we use this value. Otherwise we do a wild guess. This won't help - to correctly track the stack overrun in these exceptional cases (which - could probably happen only during startup and shutdown) but at least - lets us to pass asserts. - The problem stems from the fact that logger THDs are not real threads. - */ - if (curr) - log_thd->thread_stack= curr->thread_stack; - else - log_thd->thread_stack= (char*) &log_thd; - - log_thd->store_globals(); - - table->lock_type= TL_WRITE_CONCURRENT_INSERT; - table->db= log_thd->db; - table->db_length= log_thd->db_length; - - lex_start(log_thd); - log_thd->clear_error(); - if (simple_open_n_lock_tables(log_thd, table) || - table->table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) || - table->table->file->ha_rnd_init(0)) - error= TRUE; - else - { - table->table->use_all_columns(); - table->table->locked_by_logger= TRUE; - table->table->no_replicate= TRUE; - - /* Honor next number columns if present */ - table->table->next_number_field= table->table->found_next_number_field; - } - /* restore thread settings */ - if (curr) - curr->store_globals(); - else - { - my_pthread_setspecific_ptr(THR_THD, 0); - my_pthread_setspecific_ptr(THR_MALLOC, 0); - } - - /* - After a log table was opened, we should clear privileged thread - flag (which allows locking of a log table by a special thread, usually - the one who closed log tables temporarily). - */ - privileged_thread= 0; - DBUG_RETURN(error); -} - - Log_to_csv_event_handler::Log_to_csv_event_handler() { - /* init artificial THD's */ - general_log_thd= new THD; - /* logger thread always works with mysql database */ - general_log_thd->db= my_strdup("mysql", MYF(0)); - general_log_thd->db_length= 5; - general_log.table= 0; - - slow_log_thd= new THD; - /* logger thread always works with mysql database */ - slow_log_thd->db= my_strdup("mysql", MYF(0));; - slow_log_thd->db_length= 5; - slow_log.table= 0; - /* no privileged thread exists at the moment */ - privileged_thread= 0; } Log_to_csv_event_handler::~Log_to_csv_event_handler() { - /* now cleanup the tables */ - if (general_log_thd) - { - delete general_log_thd; - general_log_thd= NULL; - } - - if (slow_log_thd) - { - delete slow_log_thd; - slow_log_thd= NULL; - } -} - - -/* - Reopen log table of a given type - - SYNOPSIS - reopen_log_table() - - log_table_type type of the log table to open: QUERY_LOG_GENERAL - or QUERY_LOG_SLOW - - DESCRIPTION - - The function is a wrapper around open_log_table(). It is used during - FLUSH LOGS and TRUNCATE of the log tables (i.e. when we need to close - and reopen them). The difference is in the check of the - logger.is_log_tables_initialized var, which can't be done in - open_log_table(), as it makes no sense during startup. - - NOTE: this code assumes that we have logger mutex locked - - RETURN - FALSE - ok - TRUE - open_log_table() returned an error -*/ - -bool Log_to_csv_event_handler::reopen_log_table(uint log_table_type) -{ - /* don't open the log table, if it wasn't enabled during startup */ - if (!logger.is_log_tables_initialized) - return FALSE; - return open_log_table(log_table_type); } void Log_to_csv_event_handler::cleanup() { - if (opt_log) - close_log_table(QUERY_LOG_GENERAL, FALSE); - if (opt_slow_log) - close_log_table(QUERY_LOG_SLOW, FALSE); logger.is_log_tables_initialized= FALSE; } @@ -436,49 +305,88 @@ void Log_to_csv_event_handler::cleanup() */ bool Log_to_csv_event_handler:: - log_general(time_t event_time, const char *user_host, + log_general(THD *thd, time_t event_time, const char *user_host, uint user_host_len, int thread_id, const char *command_type, uint command_type_len, const char *sql_text, uint sql_text_len, CHARSET_INFO *client_cs) { - TABLE *table= general_log.table; + TABLE_LIST table_list; + TABLE *table; + bool result= TRUE; + bool need_close= FALSE; + bool need_pop= FALSE; + bool need_rnd_end= FALSE; uint field_index; + Silence_log_table_errors error_handler; + Open_tables_state open_tables_backup; + Field_timestamp *field0; + ulonglong save_thd_options; + bool save_query_start_used; + time_t save_start_time; + time_t save_time_after_lock; + time_t save_user_time; + bool save_time_zone_used; + + save_thd_options= thd->options; + thd->options&= ~OPTION_BIN_LOG; + + save_query_start_used= thd->query_start_used; + save_start_time= thd->start_time; + save_time_after_lock= thd->time_after_lock; + save_user_time= thd->user_time; + save_time_zone_used= thd->time_zone_used; + + bzero(& table_list, sizeof(TABLE_LIST)); + table_list.alias= table_list.table_name= GENERAL_LOG_NAME.str; + table_list.table_name_length= GENERAL_LOG_NAME.length; + + table_list.lock_type= TL_WRITE_CONCURRENT_INSERT; + + table_list.db= MYSQL_SCHEMA_NAME.str; + table_list.db_length= MYSQL_SCHEMA_NAME.length; + + table= open_performance_schema_table(thd, & table_list, + & open_tables_backup); + need_close= TRUE; + + if (!table || + table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) || + table->file->ha_rnd_init(0)) + goto err; + + need_rnd_end= TRUE; + + /* Honor next number columns if present */ + table->next_number_field= table->found_next_number_field; /* "INSERT INTO general_log" can generate warning sometimes. - Let's reset warnings from previous queries, - otherwise warning list can grow too much, - so thd->query gets spoiled as some point in time, - and mysql_parse() receives a broken query. QQ: this problem needs to be studied in more details. - Probably it's better to suppress warnings in logging INSERTs at all. - Comment this line and run "cast.test" to see what's happening: + Comment this 2 lines and run "cast.test" to see what's happening: */ - mysql_reset_errors(table->in_use, 1); - - /* below should never happen */ - if (unlikely(!logger.is_log_tables_initialized)) - return FALSE; + thd->push_internal_handler(& error_handler); + need_pop= TRUE; /* NOTE: we do not call restore_record() here, as all fields are filled by the Logger (=> no need to load default ones). */ - /* Set current time. Required for CURRENT_TIMESTAMP to work */ - general_log_thd->start_time= event_time; - /* We do not set a value for table->field[0], as it will use default value (which is CURRENT_TIMESTAMP). */ /* check that all columns exist */ - if (!table->field[1] || !table->field[2] || !table->field[3] || - !table->field[4] || !table->field[5]) + if (table->s->fields < 6) goto err; + DBUG_ASSERT(table->field[0]->type() == MYSQL_TYPE_TIMESTAMP); + + field0= (Field_timestamp*) (table->field[0]); + field0->set_time(); + /* do a write */ if (table->field[1]->store(user_host, user_host_len, client_cs) || table->field[2]->store((longlong) thread_id, TRUE) || @@ -500,16 +408,39 @@ bool Log_to_csv_event_handler:: table->field[field_index]->set_default(); } - /* log table entries are not replicated at the moment */ - tmp_disable_binlog(current_thd); + /* log table entries are not replicated */ + if (table->file->ha_write_row_no_binlog(table->record[0])) + { + struct tm start; + localtime_r(&event_time, &start); - table->file->ha_write_row(table->record[0]); + sql_print_error("%02d%02d%02d %2d:%02d:%02d - Failed to write to mysql.general_log", + start.tm_year % 100, start.tm_mon + 1, + start.tm_mday, start.tm_hour, + start.tm_min, start.tm_sec); + } - reenable_binlog(current_thd); + result= FALSE; - return FALSE; err: - return TRUE; + if (need_rnd_end) + { + table->file->ha_rnd_end(); + table->file->ha_release_auto_increment(); + } + if (need_pop) + thd->pop_internal_handler(); + if (need_close) + close_performance_schema_table(thd, & open_tables_backup); + + thd->options= save_thd_options; + + thd->query_start_used= save_query_start_used; + thd->start_time= save_start_time; + thd->time_after_lock= save_time_after_lock; + thd->user_time= save_user_time; + thd->time_zone_used= save_time_zone_used; + return result; } @@ -548,34 +479,61 @@ bool Log_to_csv_event_handler:: longlong query_time, longlong lock_time, bool is_command, const char *sql_text, uint sql_text_len) { - /* table variables */ - TABLE *table= slow_log.table; + TABLE_LIST table_list; + TABLE *table; + bool result= TRUE; + bool need_close= FALSE; + bool need_rnd_end= FALSE; + Open_tables_state open_tables_backup; + bool save_query_start_used; + time_t save_start_time; + time_t save_time_after_lock; + time_t save_user_time; + bool save_time_zone_used; CHARSET_INFO *client_cs= thd->variables.character_set_client; - DBUG_ENTER("log_slow"); + DBUG_ENTER("Log_to_csv_event_handler::log_slow"); - /* below should never happen */ - if (unlikely(!logger.is_log_tables_initialized)) - return FALSE; + bzero(& table_list, sizeof(TABLE_LIST)); + table_list.alias= table_list.table_name= SLOW_LOG_NAME.str; + table_list.table_name_length= SLOW_LOG_NAME.length; + + table_list.lock_type= TL_WRITE_CONCURRENT_INSERT; + + table_list.db= MYSQL_SCHEMA_NAME.str; + table_list.db_length= MYSQL_SCHEMA_NAME.length; + + save_query_start_used= thd->query_start_used; + save_start_time= thd->start_time; + save_time_after_lock= thd->time_after_lock; + save_user_time= thd->user_time; + save_time_zone_used= thd->time_zone_used; + + table= open_performance_schema_table(thd, & table_list, + & open_tables_backup); + need_close= TRUE; + + if (!table || + table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) || + table->file->ha_rnd_init(0)) + goto err; + + need_rnd_end= TRUE; + + /* Honor next number columns if present */ + table->next_number_field= table->found_next_number_field; - /* - Set start time for CURRENT_TIMESTAMP to the start of the query. - This will be default value for the field[0] - */ - slow_log_thd->start_time= query_start_arg; restore_record(table, s->default_values); // Get empty record + /* check that all columns exist */ + if (table->s->fields < 11) + goto err; + /* We do not set a value for table->field[0], as it will use default value. */ - if (!table->field[1] || !table->field[2] || !table->field[3] || - !table->field[4] || !table->field[5] || !table->field[6] || - !table->field[7] || !table->field[8] || !table->field[9] || - !table->field[10]) - goto err; - /* store the value */ if (table->field[1]->store(user_host, user_host_len, client_cs)) goto err; @@ -612,7 +570,6 @@ bool Log_to_csv_event_handler:: table->field[4]->set_null(); table->field[5]->set_null(); } - /* fill database field */ if (thd->db) { @@ -654,17 +611,71 @@ bool Log_to_csv_event_handler:: if (table->field[10]->store(sql_text,sql_text_len, client_cs)) goto err; - /* log table entries are not replicated at the moment */ - tmp_disable_binlog(current_thd); + /* log table entries are not replicated */ + if (table->file->ha_write_row_no_binlog(table->record[0])) + { + struct tm start; + localtime_r(¤t_time, &start); - /* write the row */ - table->file->ha_write_row(table->record[0]); + sql_print_error("%02d%02d%02d %2d:%02d:%02d - Failed to write to mysql.slow_log", + start.tm_year % 100, start.tm_mon + 1, + start.tm_mday, start.tm_hour, + start.tm_min, start.tm_sec); + } - reenable_binlog(current_thd); + result= FALSE; - DBUG_RETURN(0); err: - DBUG_RETURN(1); + if (need_rnd_end) + { + table->file->ha_rnd_end(); + table->file->ha_release_auto_increment(); + } + if (need_close) + close_performance_schema_table(thd, & open_tables_backup); + + thd->query_start_used= save_query_start_used; + thd->start_time= save_start_time; + thd->time_after_lock= save_time_after_lock; + thd->user_time= save_user_time; + thd->time_zone_used= save_time_zone_used; + DBUG_RETURN(result); +} + +int Log_to_csv_event_handler:: + activate_log(THD *thd, uint log_table_type) +{ + TABLE_LIST table_list; + TABLE *table; + int result; + Open_tables_state open_tables_backup; + + DBUG_ENTER("Log_to_csv_event_handler::activate_log"); + + bzero(& table_list, sizeof(TABLE_LIST)); + + if (log_table_type == QUERY_LOG_GENERAL) + { + table_list.alias= table_list.table_name= GENERAL_LOG_NAME.str; + table_list.table_name_length= GENERAL_LOG_NAME.length; + } + else + { + DBUG_ASSERT(log_table_type == QUERY_LOG_SLOW); + table_list.alias= table_list.table_name= SLOW_LOG_NAME.str; + table_list.table_name_length= SLOW_LOG_NAME.length; + } + + table_list.lock_type= TL_WRITE_CONCURRENT_INSERT; + + table_list.db= MYSQL_SCHEMA_NAME.str; + table_list.db_length= MYSQL_SCHEMA_NAME.length; + + table= open_performance_schema_table(thd, & table_list, + & open_tables_backup); + result= (table ? 0 : 1); + close_performance_schema_table(thd, & open_tables_backup); + DBUG_RETURN(result); } bool Log_to_csv_event_handler:: @@ -697,10 +708,19 @@ bool Log_to_file_event_handler:: longlong query_time, longlong lock_time, bool is_command, const char *sql_text, uint sql_text_len) { - return mysql_slow_log.write(thd, current_time, query_start_arg, - user_host, user_host_len, - query_time, lock_time, is_command, - sql_text, sql_text_len); + bool res; + + (void) pthread_mutex_lock(mysql_slow_log.get_log_lock()); + + /* TODO: MYSQL_QUERY_LOG::write is not thread-safe */ + res= mysql_slow_log.write(thd, current_time, query_start_arg, + user_host, user_host_len, + query_time, lock_time, is_command, + sql_text, sql_text_len); + + (void) pthread_mutex_unlock(mysql_slow_log.get_log_lock()); + + return res; } @@ -710,15 +730,24 @@ bool Log_to_file_event_handler:: */ bool Log_to_file_event_handler:: - log_general(time_t event_time, const char *user_host, + log_general(THD *thd, time_t event_time, const char *user_host, uint user_host_len, int thread_id, const char *command_type, uint command_type_len, const char *sql_text, uint sql_text_len, CHARSET_INFO *client_cs) { - return mysql_log.write(event_time, user_host, user_host_len, - thread_id, command_type, command_type_len, - sql_text, sql_text_len); + bool res; + + (void) pthread_mutex_lock (mysql_log.get_log_lock()); + + /* TODO: MYSQL_QUERY_LOG::write is not thread-safe */ + res= mysql_log.write(event_time, user_host, user_host_len, + thread_id, command_type, command_type_len, + sql_text, sql_text_len); + + (void) pthread_mutex_unlock (mysql_log.get_log_lock()); + + return res; } @@ -787,7 +816,7 @@ bool LOGGER::error_log_print(enum loglevel level, const char *format, void LOGGER::cleanup_base() { DBUG_ASSERT(inited == 1); - (void) pthread_mutex_destroy(&LOCK_logger); + rwlock_destroy(&LOCK_logger); if (table_log_handler) { table_log_handler->cleanup(); @@ -806,12 +835,6 @@ void LOGGER::cleanup_end() } -void LOGGER::close_log_table(uint log_table_type, bool lock_in_use) -{ - table_log_handler->close_log_table(log_table_type, lock_in_use); -} - - /* Perform basic log initialization: create file-based log handler and init error log. @@ -833,7 +856,7 @@ void LOGGER::init_base() init_error_log(LOG_FILE); file_log_handler->init_pthread_objects(); - (void) pthread_mutex_init(&LOCK_logger, MY_MUTEX_INIT_SLOW); + my_rwlock_init(&LOCK_logger, NULL); } @@ -848,29 +871,6 @@ void LOGGER::init_log_tables() } -bool LOGGER::reopen_log_table(uint log_table_type) -{ - return table_log_handler->reopen_log_table(log_table_type); -} - -bool LOGGER::reopen_log_tables() -{ - /* - we use | and not || here, to ensure that both reopen_log_table - are called, even if the first one fails - */ - if ((opt_slow_log && logger.reopen_log_table(QUERY_LOG_SLOW)) | - (opt_log && logger.reopen_log_table(QUERY_LOG_GENERAL))) - return TRUE; - return FALSE; -} - - -void LOGGER::tmp_close_log_tables(THD *thd) -{ - table_log_handler->tmp_close_log_tables(thd); -} - bool LOGGER::flush_logs(THD *thd) { int rc= 0; @@ -879,19 +879,11 @@ bool LOGGER::flush_logs(THD *thd) Now we lock logger, as nobody should be able to use logging routines while log tables are closed */ - logger.lock(); - if (logger.is_log_tables_initialized) - table_log_handler->tmp_close_log_tables(thd); // the locking happens here + logger.lock_exclusive(); /* reopen log files */ file_log_handler->flush(); - /* reopen tables in the case they were enabled */ - if (logger.is_log_tables_initialized) - { - if (reopen_log_tables()) - rc= TRUE; - } /* end of log flush */ logger.unlock(); return rc; @@ -939,7 +931,7 @@ bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length, if (thd->slave_thread) return 0; - lock(); + lock_shared(); if (!opt_slow_log) { unlock(); @@ -1011,7 +1003,7 @@ bool LOGGER::general_log_print(THD *thd, enum enum_server_command command, else id=0; /* Log from connect handler */ - lock(); + lock_shared(); if (!opt_log) { unlock(); @@ -1035,7 +1027,7 @@ bool LOGGER::general_log_print(THD *thd, enum enum_server_command command, while (*current_handler) error+= (*current_handler++)-> - log_general(current_time, user_host_buff, + log_general(thd, current_time, user_host_buff, user_host_len, id, command_name[(uint) command].str, command_name[(uint) command].length, @@ -1122,35 +1114,42 @@ void LOGGER::init_general_log(uint general_log_printer) bool LOGGER::activate_log_handler(THD* thd, uint log_type) { - bool res= 0; - lock(); + bool res= FALSE; + lock_exclusive(); switch (log_type) { case QUERY_LOG_SLOW: if (!opt_slow_log) { - if ((res= reopen_log_table(log_type))) - goto err; file_log_handler->get_mysql_slow_log()-> open_slow_log(sys_var_slow_log_path.value); init_slow_log(log_output_options); - opt_slow_log= TRUE; + if (table_log_handler->activate_log(thd, QUERY_LOG_SLOW)) + { + /* Error printed by open table in activate_log() */ + res= TRUE; + } + else + opt_slow_log= TRUE; } break; case QUERY_LOG_GENERAL: if (!opt_log) { - if ((res= reopen_log_table(log_type))) - goto err; file_log_handler->get_mysql_log()-> open_query_log(sys_var_general_log_path.value); init_general_log(log_output_options); - opt_log= TRUE; + if (table_log_handler->activate_log(thd, QUERY_LOG_GENERAL)) + { + /* Error printed by open table in activate_log() */ + res= TRUE; + } + else + opt_log= TRUE; } break; default: DBUG_ASSERT(0); } -err: unlock(); return res; } @@ -1158,23 +1157,17 @@ err: void LOGGER::deactivate_log_handler(THD *thd, uint log_type) { - TABLE_LIST *table_list; my_bool *tmp_opt= 0; MYSQL_LOG *file_log; - THD *log_thd; switch (log_type) { case QUERY_LOG_SLOW: - table_list= &table_log_handler->slow_log; tmp_opt= &opt_slow_log; file_log= file_log_handler->get_mysql_slow_log(); - log_thd= table_log_handler->slow_log_thd; break; case QUERY_LOG_GENERAL: - table_list= &table_log_handler->general_log; tmp_opt= &opt_log; file_log= file_log_handler->get_mysql_log(); - log_thd= table_log_handler->general_log_thd; break; default: assert(0); // Impossible @@ -1183,81 +1176,16 @@ void LOGGER::deactivate_log_handler(THD *thd, uint log_type) if (!(*tmp_opt)) return; - if (is_log_tables_initialized) - lock_and_wait_for_table_name(log_thd, table_list); - lock(); - - if (is_log_tables_initialized) - { - VOID(pthread_mutex_lock(&LOCK_open)); - close_log_table(log_type, TRUE); - table_list->table= 0; - query_cache_invalidate3(log_thd, table_list, 0); - unlock_table_name(log_thd, table_list); - VOID(pthread_mutex_unlock(&LOCK_open)); - } + lock_exclusive(); file_log->close(0); *tmp_opt= FALSE; unlock(); } -/* - Close log tables temporarily. The thread which closed - them this way can lock them in any mode it needs. - NOTE: one should call logger.lock() before entering this - function. -*/ -void Log_to_csv_event_handler::tmp_close_log_tables(THD *thd) -{ - TABLE_LIST close_slow_log, close_general_log; - - /* fill lists, we will need to perform operations on tables */ - bzero((char*) &close_slow_log, sizeof(TABLE_LIST)); - close_slow_log.alias= close_slow_log.table_name=(char*) "slow_log"; - close_slow_log.table_name_length= 8; - close_slow_log.db= (char*) "mysql"; - close_slow_log.db_length= 5; - - bzero((char*) &close_general_log, sizeof(TABLE_LIST)); - close_general_log.alias= close_general_log.table_name=(char*) "general_log"; - close_general_log.table_name_length= 11; - close_general_log.db= (char*) "mysql"; - close_general_log.db_length= 5; - - privileged_thread= thd; - - VOID(pthread_mutex_lock(&LOCK_open)); - /* - NOTE: in fact, the first parameter used in query_cache_invalidate3() - could be any non-NULL THD, as the underlying code makes certain - assumptions about this. - Here we use one of the logger handler THD's. Simply because it - seems appropriate. - */ - if (opt_log) - { - close_log_table(QUERY_LOG_GENERAL, TRUE); - query_cache_invalidate3(general_log_thd, &close_general_log, 0); - } - if (opt_slow_log) - { - close_log_table(QUERY_LOG_SLOW, TRUE); - query_cache_invalidate3(general_log_thd, &close_slow_log, 0); - } - VOID(pthread_mutex_unlock(&LOCK_open)); -} - /* the parameters are unused for the log tables */ bool Log_to_csv_event_handler::init() { - /* - we use | and not || here, to ensure that both open_log_table - are called, even if the first one fails - */ - if ((opt_log && open_log_table(QUERY_LOG_GENERAL)) | - (opt_slow_log && open_log_table(QUERY_LOG_SLOW))) - return 1; return 0; } @@ -1268,7 +1196,7 @@ int LOGGER::set_handlers(uint error_log_printer, /* error log table is not supported yet */ DBUG_ASSERT(error_log_printer < LOG_TABLE); - lock(); + lock_exclusive(); if ((slow_log_printer & LOG_TABLE || general_log_printer & LOG_TABLE) && !is_log_tables_initialized) @@ -1290,72 +1218,6 @@ int LOGGER::set_handlers(uint error_log_printer, } -/* - Close log table of a given type (general or slow log) - - SYNOPSIS - close_log_table() - - log_table_type type of the log table to close: QUERY_LOG_GENERAL - or QUERY_LOG_SLOW - lock_in_use Set to TRUE if the caller owns LOCK_open. FALSE otherwise. - - DESCRIPTION - - The function closes a log table. It is invoked (1) when we need to reopen - log tables (e.g. FLUSH LOGS or TRUNCATE on the log table is being - executed) or (2) during shutdown. -*/ - -void Log_to_csv_event_handler:: - close_log_table(uint log_table_type, bool lock_in_use) -{ - THD *log_thd, *curr= current_thd; - TABLE_LIST *table; - - if (!logger.is_log_table_enabled(log_table_type)) - return; /* do nothing */ - - switch (log_table_type) { - case QUERY_LOG_GENERAL: - log_thd= general_log_thd; - table= &general_log; - break; - case QUERY_LOG_SLOW: - log_thd= slow_log_thd; - table= &slow_log; - break; - default: - assert(0); // Impossible - } - - /* - Set thread stack start for the logger thread. See comment in - open_log_table() for details. - */ - if (curr) - log_thd->thread_stack= curr->thread_stack; - else - log_thd->thread_stack= (char*) &log_thd; - - /* close the table */ - log_thd->store_globals(); - table->table->file->ha_rnd_end(); - table->table->file->ha_release_auto_increment(); - /* discard logger mark before unlock*/ - table->table->locked_by_logger= FALSE; - close_thread_tables(log_thd, lock_in_use); - - if (curr) - curr->store_globals(); - else - { - my_pthread_setspecific_ptr(THR_THD, 0); - my_pthread_setspecific_ptr(THR_MALLOC, 0); - } -} - - /* Save position of binary log transaction cache. |