From: Jon Olav Hauglid Date: November 14 2012 10:15am Subject: bzr push into mysql-trunk-wl6613 branch (jon.hauglid:4987 to 4988) WL#6613 List-Archive: http://lists.mysql.com/commits/145269 Message-Id: <20121114101559.2095.2054.4988@atum08.no.oracle.com> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 4988 Jon Olav Hauglid 2012-11-14 WL#6613: Refactor logging code - split logging and binlogging code Remove MYSQL_LOG and move implementation to MYSQL_QUERY_LOG and MYSQL_BINARY_LOG. Move replication code out of log.h and log.cc. Remove dead code. Update log.h/log.cc according to current code standard. modified: sql/binlog.cc sql/binlog.h sql/log.cc sql/log.h sql/mysqld.cc sql/rpl_rli.cc sql/rpl_tblmap.h sql/sql_alter.cc sql/sql_class.h sql/sql_table.cc sql/sys_vars.cc 4987 Jon Olav Hauglid 2012-11-14 Change tree name modified: .bzr-mysql/default.conf === modified file 'sql/binlog.cc' --- a/sql/binlog.cc 2012-11-13 18:27:55 +0000 +++ b/sql/binlog.cc 2012-11-14 10:15:19 +0000 @@ -31,6 +31,7 @@ #include "rpl_mi.h" #include #include +#include // For test_if_number using std::max; using std::min; @@ -64,7 +65,7 @@ bool opt_binlog_order_commits= true; const char *log_bin_index= 0; const char *log_bin_basename= 0; -MYSQL_BIN_LOG mysql_bin_log(&sync_binlog_period); +MYSQL_BIN_LOG mysql_bin_log(&sync_binlog_period, WRITE_CACHE); static int binlog_init(void *p); static int binlog_start_trans_and_stmt(THD *thd, Log_event *start_event); @@ -1629,6 +1630,35 @@ static int binlog_savepoint_rollback(han DBUG_RETURN(0); } +/** + purge logs, master and slave sides both, related error code + convertor. + Called from @c purge_error_message(), @c MYSQL_BIN_LOG::reset_logs() + + @param res an internal to purging routines error code + + @return the user level error code ER_* +*/ +static uint purge_log_get_error_code(int res) +{ + uint errcode= 0; + + switch (res) { + case 0: break; + case LOG_INFO_EOF: errcode= ER_UNKNOWN_TARGET_BINLOG; break; + case LOG_INFO_IO: errcode= ER_IO_ERR_LOG_INDEX_READ; break; + case LOG_INFO_INVALID:errcode= ER_BINLOG_PURGE_PROHIBITED; break; + case LOG_INFO_SEEK: errcode= ER_FSEEK_FAIL; break; + case LOG_INFO_MEM: errcode= ER_OUT_OF_RESOURCES; break; + case LOG_INFO_FATAL: errcode= ER_BINLOG_PURGE_FATAL_ERR; break; + case LOG_INFO_IN_USE: errcode= ER_LOG_IN_USE; break; + case LOG_INFO_EMFILE: errcode= ER_BINLOG_PURGE_EMFILE; break; + default: errcode= ER_LOG_PURGE_UNKNOWN_ERR; break; + } + + return errcode; +} + #ifdef HAVE_REPLICATION /* @@ -2235,8 +2265,14 @@ bool mysql_show_binlog_events(THD* thd) #endif /* HAVE_REPLICATION */ -MYSQL_BIN_LOG::MYSQL_BIN_LOG(uint *sync_period) - :bytes_written(0), file_id(1), open_count(1), +MYSQL_BIN_LOG::MYSQL_BIN_LOG(uint *sync_period, + enum cache_type io_cache_type_arg) + :name(NULL), write_error(false), inited(false), + log_state(LOG_CLOSED), io_cache_type(io_cache_type_arg) +#ifdef HAVE_PSI_INTERFACE + ,m_key_LOCK_log(key_LOG_LOCK_log), +#endif + bytes_written(0), file_id(1), open_count(1), sync_period_ptr(sync_period), sync_counter(0), m_prep_xids(0), is_relay_log(0), signal_cnt(0), @@ -2250,6 +2286,7 @@ MYSQL_BIN_LOG::MYSQL_BIN_LOG(uint *sync_ called only in main(). Doing initialization here would make it happen before main(). */ + memset(&log_file, 0, sizeof(log_file)); index_file_name[0] = 0; memset(&index_file, 0, sizeof(index_file)); memset(&purge_index_file, 0, sizeof(purge_index_file)); @@ -2280,7 +2317,9 @@ void MYSQL_BIN_LOG::cleanup() void MYSQL_BIN_LOG::init_pthread_objects() { - MYSQL_LOG::init_pthread_objects(); + DBUG_ASSERT(inited == 0); + inited= 1; + mysql_mutex_init(m_key_LOCK_log, &LOCK_log, MY_MUTEX_INIT_SLOW); mysql_mutex_init(m_key_LOCK_index, &LOCK_index, MY_MUTEX_INIT_SLOW); mysql_mutex_init(m_key_LOCK_commit, &LOCK_commit, MY_MUTEX_INIT_FAST); mysql_mutex_init(m_key_LOCK_sync, &LOCK_sync, MY_MUTEX_INIT_FAST); @@ -2297,6 +2336,310 @@ void MYSQL_BIN_LOG::init_pthread_objects ); } + +/** + Check if a string is a valid number. + + @param str String to test + @param res Store value here + @param allow_wildcards Set to 1 if we should ignore '%' and '_' + + @note + For the moment the allow_wildcards argument is not used + Should be move to some other file. + + @retval + 1 String is a number + @retval + 0 String is not a number +*/ + +static bool test_if_number(register const char *str, + ulong *res, bool allow_wildcards) +{ + reg2 int flag; + const char *start; + DBUG_ENTER("test_if_number"); + + flag=0; start=str; + while (*str++ == ' ') ; + if (*--str == '-' || *str == '+') + str++; + while (my_isdigit(files_charset_info,*str) || + (allow_wildcards && (*str == wild_many || *str == wild_one))) + { + flag=1; + str++; + } + if (*str == '.') + { + for (str++ ; + my_isdigit(files_charset_info,*str) || + (allow_wildcards && (*str == wild_many || *str == wild_one)) ; + str++, flag=1) ; + } + if (*str != 0 || flag == 0) + DBUG_RETURN(0); + if (res) + *res=atol(start); + DBUG_RETURN(1); /* Number ok */ +} /* test_if_number */ + + +/* + Maximum unique log filename extension. + Note: setting to 0x7FFFFFFF due to atol windows + overflow/truncate. + */ +#define MAX_LOG_UNIQUE_FN_EXT 0x7FFFFFFF + +/* + Number of warnings that will be printed to error log + before extension number is exhausted. +*/ +#define LOG_WARN_UNIQUE_FN_EXT_LEFT 1000 + +/** + Find a unique filename for 'filename.#'. + + Set '#' to the number next to the maximum found in the most + recent log file extension. + + This function will return nonzero if: (i) the generated name + exceeds FN_REFLEN; (ii) if the number of extensions is exhausted; + or (iii) some other error happened while examining the filesystem. + + @return + nonzero if not possible to get unique filename. +*/ + +static int find_uniq_filename(char *name) +{ + uint i; + char buff[FN_REFLEN], ext_buf[FN_REFLEN]; + struct st_my_dir *dir_info; + reg1 struct fileinfo *file_info; + ulong max_found= 0, next= 0, number= 0; + size_t buf_length, length; + char *start, *end; + int error= 0; + DBUG_ENTER("find_uniq_filename"); + + length= dirname_part(buff, name, &buf_length); + start= name + length; + end= strend(start); + + *end='.'; + length= (size_t) (end - start + 1); + + if ((DBUG_EVALUATE_IF("error_unique_log_filename", 1, + !(dir_info= my_dir(buff,MYF(MY_DONT_SORT)))))) + { // This shouldn't happen + strmov(end,".1"); // use name+1 + DBUG_RETURN(1); + } + file_info= dir_info->dir_entry; + for (i= dir_info->number_off_files ; i-- ; file_info++) + { + if (memcmp(file_info->name, start, length) == 0 && + test_if_number(file_info->name+length, &number,0)) + { + set_if_bigger(max_found,(ulong) number); + } + } + my_dirend(dir_info); + + /* check if reached the maximum possible extension number */ + if (max_found == MAX_LOG_UNIQUE_FN_EXT) + { + sql_print_error("Log filename extension number exhausted: %06lu. \ +Please fix this by archiving old logs and \ +updating the index files.", max_found); + error= 1; + goto end; + } + + next= max_found + 1; + if (sprintf(ext_buf, "%06lu", next)<0) + { + error= 1; + goto end; + } + *end++='.'; + + /* + Check if the generated extension size + the file name exceeds the + buffer size used. If one did not check this, then the filename might be + truncated, resulting in error. + */ + if (((strlen(ext_buf) + (end - name)) >= FN_REFLEN)) + { + sql_print_error("Log filename too large: %s%s (%zu). \ +Please fix this by archiving old logs and updating the \ +index files.", name, ext_buf, (strlen(ext_buf) + (end - name))); + error= 1; + goto end; + } + + if (sprintf(end, "%06lu", next)<0) + { + error= 1; + goto end; + } + + /* print warning if reaching the end of available extensions. */ + if ((next > (MAX_LOG_UNIQUE_FN_EXT - LOG_WARN_UNIQUE_FN_EXT_LEFT))) + sql_print_warning("Next log extension: %lu. \ +Remaining log filename extensions: %lu. \ +Please consider archiving some logs.", next, (MAX_LOG_UNIQUE_FN_EXT - next)); + +end: + DBUG_RETURN(error); +} + + +int MYSQL_BIN_LOG::generate_new_name(char *new_name, const char *log_name) +{ + fn_format(new_name, log_name, mysql_data_home, "", 4); + if (!fn_ext(log_name)[0]) + { + if (find_uniq_filename(new_name)) + { + my_printf_error(ER_NO_UNIQUE_LOGFILE, ER(ER_NO_UNIQUE_LOGFILE), + MYF(ME_FATALERROR), log_name); + sql_print_error(ER(ER_NO_UNIQUE_LOGFILE), log_name); + return 1; + } + } + return 0; +} + + +/** + @todo + The following should be using fn_format(); We just need to + first change fn_format() to cut the file name if it's too long. +*/ +const char *MYSQL_BIN_LOG::generate_name(const char *log_name, + const char *suffix, + char *buff) +{ + if (!log_name || !log_name[0]) + { + strmake(buff, pidfile_name, FN_REFLEN - strlen(suffix) - 1); + return (const char *) + fn_format(buff, buff, "", suffix, MYF(MY_REPLACE_EXT|MY_REPLACE_DIR)); + } + // get rid of extension to avoid problems + + char *p= fn_ext(log_name); + uint length= (uint) (p - log_name); + strmake(buff, log_name, min(length, FN_REFLEN-1)); + return (const char*)buff; +} + + +bool MYSQL_BIN_LOG::init_and_set_log_file_name(const char *log_name, + const char *new_name) +{ + if (new_name && !strmov(log_file_name, new_name)) + return TRUE; + else if (!new_name && generate_new_name(log_file_name, log_name)) + return TRUE; + + return FALSE; +} + + +/* + Open a (new) log file. + + SYNOPSIS + open() + + log_name The name of the log to open + new_name The new name for the logfile. This is only needed + when the method is used to open the binlog file. + + DESCRIPTION + Open the logfile, init IO_CACHE and write startup messages + (in case of general and slow query logs). + + RETURN VALUES + 0 ok + 1 error +*/ + +bool MYSQL_BIN_LOG::open( +#ifdef HAVE_PSI_INTERFACE + PSI_file_key log_file_key, +#endif + const char *log_name, + const char *new_name) +{ + File file= -1; + my_off_t pos= 0; + int open_flags= O_CREAT | O_BINARY; + DBUG_ENTER("MYSQL_BIN_LOG::open"); + + write_error= 0; + + if (!(name= my_strdup(log_name, MYF(MY_WME)))) + { + name= (char *)log_name; // for the error message + goto err; + } + + if (init_and_set_log_file_name(name, new_name)) + goto err; + + if (io_cache_type == SEQ_READ_APPEND) + open_flags |= O_RDWR | O_APPEND; + else + open_flags |= O_WRONLY; + + db[0]= 0; + +#ifdef HAVE_PSI_INTERFACE + /* Keep the key for reopen */ + m_log_file_key= log_file_key; +#endif + + if ((file= mysql_file_open(log_file_key, + log_file_name, open_flags, + MYF(MY_WME | ME_WAITTANG))) < 0) + goto err; + + if ((pos= mysql_file_tell(file, MYF(MY_WME))) == MY_FILEPOS_ERROR) + { + if (my_errno == ESPIPE) + pos= 0; + else + goto err; + } + + if (init_io_cache(&log_file, file, IO_SIZE, io_cache_type, pos, 0, + MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL))) + goto err; + + log_state= LOG_OPENED; + DBUG_RETURN(0); + +err: + sql_print_error("Could not use %s for logging (error %d). \ +Turning logging off for the whole duration of the MySQL server process. \ +To turn it on again: fix the cause, \ +shutdown the MySQL server and restart it.", name, errno); + if (file >= 0) + mysql_file_close(file, MYF(0)); + end_io_cache(&log_file); + my_free(name); + name= NULL; + log_state= LOG_CLOSED; + DBUG_RETURN(1); +} + + bool MYSQL_BIN_LOG::open_index_file(const char *index_file_name_arg, const char *log_name, bool need_lock_index) { @@ -2691,7 +3034,6 @@ end: bool MYSQL_BIN_LOG::open_binlog(const char *log_name, const char *new_name, - enum cache_type io_cache_type_arg, ulong max_size_arg, bool null_created_arg, bool need_lock_index, @@ -2705,8 +3047,7 @@ bool MYSQL_BIN_LOG::open_binlog(const ch DBUG_ENTER("MYSQL_BIN_LOG::open_binlog(const char *, ...)"); DBUG_PRINT("enter",("name: %s", log_name)); - if (init_and_set_log_file_name(log_name, new_name, LOG_BIN, - io_cache_type_arg)) + if (init_and_set_log_file_name(log_name, new_name)) { sql_print_error("MYSQL_BIN_LOG::open failed to generate new file name."); DBUG_RETURN(1); @@ -2724,7 +3065,7 @@ bool MYSQL_BIN_LOG::open_binlog(const ch it may be good to consider what actually happens when open_purge_index_file succeeds but register or sync fails. - Perhaps we might need the code below in MYSQL_LOG_BIN::cleanup + Perhaps we might need the code below in MYSQL_BIN_LOG::cleanup for "real life" purposes as well? */ DBUG_EXECUTE_IF("fault_injection_registering_index", { @@ -2744,11 +3085,11 @@ bool MYSQL_BIN_LOG::open_binlog(const ch write_error= 0; /* open the main log file */ - if (MYSQL_LOG::open( + if (open( #ifdef HAVE_PSI_INTERFACE m_key_file_log, #endif - log_name, LOG_BIN, new_name, io_cache_type_arg)) + log_name, new_name)) { #ifdef HAVE_REPLICATION close_purge_index_file(); @@ -3414,7 +3755,7 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd) #endif if (!open_index_file(index_file_name, 0, false/*need_lock_index=false*/)) - if ((error= open_binlog(save_name, 0, io_cache_type, + if ((error= open_binlog(save_name, 0, max_size, false, false/*need_lock_index=false*/, false/*need_sid_lock=false*/, @@ -4395,7 +4736,7 @@ int MYSQL_BIN_LOG::new_file_impl(bool ne { /* reopen the binary log file. */ file_to_open= new_name_ptr; - error= open_binlog(old_name, new_name_ptr, io_cache_type, + error= open_binlog(old_name, new_name_ptr, max_size, true, false/*need_lock_index=false*/, true/*need_sid_lock=true*/, @@ -5463,7 +5804,30 @@ void MYSQL_BIN_LOG::close(uint exiting) } /* this will cleanup IO_CACHE, sync and close the file */ - MYSQL_LOG::close(exiting); + if (log_state == LOG_OPENED) + { + end_io_cache(&log_file); + + if (mysql_file_sync(log_file.file, MYF(MY_WME)) && ! write_error) + { + char errbuf[MYSYS_STRERROR_SIZE]; + write_error= 1; + sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), name, errno, + my_strerror(errbuf, sizeof(errbuf), errno)); + } + + if (mysql_file_close(log_file.file, MYF(MY_WME)) && ! write_error) + { + char errbuf[MYSYS_STRERROR_SIZE]; + write_error= 1; + sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), name, errno, + my_strerror(errbuf, sizeof(errbuf), errno)); + } + } + + log_state= (exiting & LOG_CLOSE_TO_BE_OPENED) ? LOG_TO_BE_OPENED : LOG_CLOSED; + my_free(name); + name= NULL; } /* @@ -5548,7 +5912,7 @@ int MYSQL_BIN_LOG::open_binlog(const cha if (using_heuristic_recover()) { /* generate a new binlog to mask a corrupted one */ - open_binlog(opt_name, 0, WRITE_CACHE, max_binlog_size, false, + open_binlog(opt_name, 0, max_binlog_size, false, true/*need_lock_index=true*/, true/*need_sid_lock=true*/, NULL); @@ -8227,7 +8591,7 @@ int THD::binlog_query(THD::enum_binlog_q */ case THD::STMT_QUERY_TYPE: /* - The MYSQL_LOG::write() function will set the STMT_END_F flag and + The MYSQL_BIN_LOG::write() function will set the STMT_END_F flag and flush the pending rows event if necessary. */ { === modified file 'sql/binlog.h' --- a/sql/binlog.h 2012-09-18 12:32:43 +0000 +++ b/sql/binlog.h 2012-11-14 10:15:19 +0000 @@ -208,11 +208,70 @@ private: mysql_mutex_t m_lock_done; }; +/* log info errors */ +#define LOG_INFO_EOF -1 +#define LOG_INFO_IO -2 +#define LOG_INFO_INVALID -3 +#define LOG_INFO_SEEK -4 +#define LOG_INFO_MEM -6 +#define LOG_INFO_FATAL -7 +#define LOG_INFO_IN_USE -8 +#define LOG_INFO_EMFILE -9 + +/* bitmap to MYSQL_BIN_LOG::close() */ +#define LOG_CLOSE_INDEX 1 +#define LOG_CLOSE_TO_BE_OPENED 2 +#define LOG_CLOSE_STOP_EVENT 4 -class MYSQL_BIN_LOG: public TC_LOG, private MYSQL_LOG +#ifdef HAVE_PSI_INTERFACE +extern PSI_mutex_key key_LOG_INFO_lock; +#endif + +/* + Note that we destroy the lock mutex in the desctructor here. + This means that object instances cannot be destroyed/go out of scope, + until we have reset thd->current_linfo to NULL; + */ +typedef struct st_log_info +{ + char log_file_name[FN_REFLEN]; + my_off_t index_file_offset, index_file_start_offset; + my_off_t pos; + bool fatal; // if the purge happens to give us a negative offset + mysql_mutex_t lock; + st_log_info() + : index_file_offset(0), index_file_start_offset(0), + pos(0), fatal(0) + { + log_file_name[0] = '\0'; + mysql_mutex_init(key_LOG_INFO_lock, &lock, MY_MUTEX_INIT_FAST); + } + ~st_log_info() { mysql_mutex_destroy(&lock);} +} LOG_INFO; + +/* + TODO use mmap instead of IO_CACHE for binlog + (mmap+fsync is two times faster than write+fsync) +*/ + +class MYSQL_BIN_LOG: public TC_LOG { - private: + enum enum_log_state { LOG_OPENED, LOG_CLOSED, LOG_TO_BE_OPENED }; + + /* LOCK_log is inited by init_pthread_objects() */ + mysql_mutex_t LOCK_log; + char *name; + char log_file_name[FN_REFLEN]; + char db[NAME_LEN + 1]; + bool write_error, inited; + IO_CACHE log_file; + volatile enum_log_state log_state; + const enum cache_type io_cache_type; #ifdef HAVE_PSI_INTERFACE + /** Instrumentation key to use for file io in @c log_file */ + PSI_file_key m_log_file_key; + /** The instrumentation key to use for @ LOCK_log. */ + PSI_mutex_key m_key_LOCK_log; /** The instrumentation key to use for @ LOCK_index. */ PSI_mutex_key m_key_LOCK_index; @@ -343,9 +402,20 @@ class MYSQL_BIN_LOG: public TC_LOG, priv Stage_manager stage_manager; void do_flush(THD *thd); + bool open( +#ifdef HAVE_PSI_INTERFACE + PSI_file_key log_file_key, +#endif + const char *log_name, + const char *new_name); + bool init_and_set_log_file_name(const char *log_name, + const char *new_name); + int generate_new_name(char *new_name, const char *log_name); + public: - using MYSQL_LOG::generate_name; - using MYSQL_LOG::is_open; + const char *generate_name(const char *log_name, const char *suffix, + char *buff); + bool is_open() const { return log_state != LOG_CLOSED; } /* This is relay log */ bool is_relay_log; @@ -386,7 +456,8 @@ public: */ uint8 relay_log_checksum_alg; - MYSQL_BIN_LOG(uint *sync_period); + MYSQL_BIN_LOG(uint *sync_period, + enum cache_type io_cache_type_arg); /* note that there's no destructor ~MYSQL_BIN_LOG() ! The reason is that we don't want it to be automatically called @@ -510,8 +581,6 @@ public: @param log_name Name of binlog @param new_name Name of binlog, too. todo: what's the difference between new_name and log_name? - @param io_cache_type_arg Specifies how the IO cache is opened: - read-only or read-write. @param max_size The size at which this binlog will be rotated. @param null_created If false, and a Format_description_log_event is written, then the Format_description_log_event will have the @@ -525,7 +594,6 @@ public: */ bool open_binlog(const char *log_name, const char *new_name, - enum cache_type io_cache_type_arg, ulong max_size, bool null_created, bool need_lock_index, bool need_sid_lock, @@ -656,6 +724,7 @@ void check_binlog_stmt_cache_size(THD *t bool binlog_enabled(); void register_binlog_handler(THD *thd, bool trx); int gtid_empty_group_log_and_cleanup(THD *thd); +int query_error_code(THD *thd, bool not_killed); extern const char *log_bin_index; extern const char *log_bin_basename; === modified file 'sql/log.cc' --- a/sql/log.cc 2012-11-06 14:16:49 +0000 +++ b/sql/log.cc 2012-11-14 10:15:19 +0000 @@ -38,7 +38,6 @@ #include #include -#include // For test_if_number #ifdef _WIN32 #include "message.h" @@ -47,12 +46,24 @@ using std::min; using std::max; -/* max size of the log message */ -#define MAX_LOG_BUFFER_SIZE 1024 -#define MAX_TIME_SIZE 32 +enum enum_slow_query_log_table_field +{ + SQLT_FIELD_START_TIME = 0, + SQLT_FIELD_USER_HOST, + SQLT_FIELD_QUERY_TIME, + SQLT_FIELD_LOCK_TIME, + SQLT_FIELD_ROWS_SENT, + SQLT_FIELD_ROWS_EXAMINED, + SQLT_FIELD_DATABASE, + SQLT_FIELD_LAST_INSERT_ID, + SQLT_FIELD_INSERT_ID, + SQLT_FIELD_SERVER_ID, + SQLT_FIELD_SQL_TEXT, + SQLT_FIELD_THREAD_ID, + SQLT_FIELD_COUNT +}; -static -const TABLE_FIELD_TYPE slow_query_log_table_fields[SQLT_FIELD_COUNT] = +static const TABLE_FIELD_TYPE slow_query_log_table_fields[SQLT_FIELD_COUNT] = { { { C_STRING_WITH_LEN("start_time") }, @@ -117,25 +128,21 @@ const TABLE_FIELD_TYPE slow_query_log_ta }; static const TABLE_FIELD_DEF - slow_query_log_table_def= {SQLT_FIELD_COUNT, slow_query_log_table_fields}; +slow_query_log_table_def= {SQLT_FIELD_COUNT, slow_query_log_table_fields}; + -class Slow_query_log_table_intact : public Table_check_intact +enum enum_general_log_table_field { -protected: - void report_error(uint, const char *fmt, ...) - { - va_list args; - va_start(args, fmt); - error_log_print(ERROR_LEVEL, fmt, args); - va_end(args); - } + GLT_FIELD_EVENT_TIME = 0, + GLT_FIELD_USER_HOST, + GLT_FIELD_THREAD_ID, + GLT_FIELD_SERVER_ID, + GLT_FIELD_COMMAND_TYPE, + GLT_FIELD_ARGUMENT, + GLT_FIELD_COUNT }; -/** In case of an error, a message is printed to the error log. */ -static Slow_query_log_table_intact sqlt_intact; - -static -const TABLE_FIELD_TYPE general_log_table_fields[GLT_FIELD_COUNT] = +static const TABLE_FIELD_TYPE general_log_table_fields[GLT_FIELD_COUNT] = { { { C_STRING_WITH_LEN("event_time") }, @@ -172,7 +179,8 @@ const TABLE_FIELD_TYPE general_log_table static const TABLE_FIELD_DEF general_log_table_def= {GLT_FIELD_COUNT, general_log_table_fields}; -class General_log_table_intact : public Table_check_intact + +class Query_log_table_intact : public Table_check_intact { protected: void report_error(uint, const char *fmt, ...) @@ -185,41 +193,11 @@ protected: }; /** In case of an error, a message is printed to the error log. */ -static General_log_table_intact glt_intact; - -LOGGER logger; - -static bool test_if_number(const char *str, - ulong *res, bool allow_wildcards); +static Query_log_table_intact log_table_intact; -/** - purge logs, master and slave sides both, related error code - convertor. - Called from @c purge_error_message(), @c MYSQL_BIN_LOG::reset_logs() - - @param res an internal to purging routines error code - - @return the user level error code ER_* -*/ -uint purge_log_get_error_code(int res) -{ - uint errcode= 0; - switch (res) { - case 0: break; - case LOG_INFO_EOF: errcode= ER_UNKNOWN_TARGET_BINLOG; break; - case LOG_INFO_IO: errcode= ER_IO_ERR_LOG_INDEX_READ; break; - case LOG_INFO_INVALID:errcode= ER_BINLOG_PURGE_PROHIBITED; break; - case LOG_INFO_SEEK: errcode= ER_FSEEK_FAIL; break; - case LOG_INFO_MEM: errcode= ER_OUT_OF_RESOURCES; break; - case LOG_INFO_FATAL: errcode= ER_BINLOG_PURGE_FATAL_ERR; break; - case LOG_INFO_IN_USE: errcode= ER_LOG_IN_USE; break; - case LOG_INFO_EMFILE: errcode= ER_BINLOG_PURGE_EMFILE; break; - default: errcode= ER_LOG_PURGE_UNKNOWN_ERR; break; - } +LOGGER logger; - return errcode; -} /** Silence all errors and warnings reported when performing a write @@ -228,6 +206,7 @@ uint purge_log_get_error_code(int res) 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 { char m_message[MYSQL_ERRMSG_SIZE]; @@ -244,22 +223,15 @@ public: const char* sql_state, Sql_condition::enum_severity_level level, const char* msg, - Sql_condition ** cond_hdl); + Sql_condition ** cond_hdl) + { + *cond_hdl= NULL; + strmake(m_message, msg, sizeof(m_message)-1); + return true; + } const char *message() const { return m_message; } }; -bool -Silence_log_table_errors::handle_condition(THD *, - uint, - const char*, - Sql_condition::enum_severity_level, - const char* msg, - Sql_condition ** cond_hdl) -{ - *cond_hdl= NULL; - strmake(m_message, msg, sizeof(m_message)-1); - return TRUE; -} sql_print_message_func sql_print_message_handlers[3] = { @@ -268,6 +240,7 @@ sql_print_message_func sql_print_message sql_print_error }; + /** Create the name of the log specified. @@ -280,6 +253,7 @@ sql_print_message_func sql_print_message @returns Pointer to new string containing the name. */ + char *make_log_name(char *buff, const char *name, const char* log_ext) { strmake(buff, name, FN_REFLEN-5); @@ -287,7 +261,8 @@ char *make_log_name(char *buff, const ch MYF(MY_UNPACK_FILENAME|MY_REPLACE_EXT)); } -bool LOGGER::is_log_table_enabled(uint log_table_type) + +bool LOGGER::is_log_table_enabled(enum_log_table_type log_table_type) { switch (log_table_type) { case QUERY_LOG_SLOW: @@ -298,14 +273,17 @@ bool LOGGER::is_log_table_enabled(uint l && (log_output_options & LOG_TABLE)); default: DBUG_ASSERT(0); - return FALSE; /* make compiler happy */ + return false; /* make compiler happy */ } } /* Check if a given table is opened log table */ -int check_if_log_table(size_t db_len, const char *db, size_t table_name_len, - const char *table_name, bool check_if_opened) + +enum_log_table_type check_if_log_table(size_t db_len, const char *db, + size_t table_name_len, + const char *table_name, + bool check_if_opened) { if (db_len == 5 && !(lower_case_table_names ? @@ -319,7 +297,7 @@ int check_if_log_table(size_t db_len, co { if (!check_if_opened || logger.is_log_table_enabled(QUERY_LOG_GENERAL)) return QUERY_LOG_GENERAL; - return 0; + return NO_LOG_TABLE; } if (table_name_len == 8 && !(lower_case_table_names ? @@ -328,20 +306,10 @@ int check_if_log_table(size_t db_len, co { if (!check_if_opened || logger.is_log_table_enabled(QUERY_LOG_SLOW)) return QUERY_LOG_SLOW; - return 0; + return NO_LOG_TABLE; } } - return 0; -} - - -Log_to_csv_event_handler::Log_to_csv_event_handler() -{ -} - - -Log_to_csv_event_handler::~Log_to_csv_event_handler() -{ + return NO_LOG_TABLE; } @@ -350,7 +318,6 @@ void Log_to_csv_event_handler::cleanup() logger.is_log_tables_initialized= FALSE; } -/* log event handlers */ /** Log command to the general log table @@ -382,12 +349,15 @@ void Log_to_csv_event_handler::cleanup() @retval TRUE error occured */ -bool Log_to_csv_event_handler:: - log_general(THD *thd, time_t event_time, const char *user_host, - uint user_host_len, my_thread_id thread_id, - const char *command_type, uint command_type_len, - const char *sql_text, uint sql_text_len, - const CHARSET_INFO *client_cs) +bool Log_to_csv_event_handler::log_general(THD *thd, time_t event_time, + const char *user_host, + uint user_host_len, + my_thread_id thread_id, + const char *command_type, + uint command_type_len, + const char *sql_text, + uint sql_text_len, + const CHARSET_INFO *client_cs) { TABLE_LIST table_list; TABLE *table; @@ -434,7 +404,7 @@ bool Log_to_csv_event_handler:: need_close= TRUE; - if (glt_intact.check(table_list.table, &general_log_table_def)) + if (log_table_intact.check(table_list.table, &general_log_table_def)) goto err; if (table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) || @@ -552,11 +522,13 @@ err: TRUE - error occured */ -bool Log_to_csv_event_handler:: - log_slow(THD *thd, time_t current_time, time_t query_start_arg, - const char *user_host, uint user_host_len, - ulonglong query_utime, ulonglong lock_utime, bool is_command, - const char *sql_text, uint sql_text_len) +bool Log_to_csv_event_handler::log_slow(THD *thd, time_t current_time, + time_t query_start_arg, + const char *user_host, + uint user_host_len, + ulonglong query_utime, + ulonglong lock_utime, bool is_command, + const char *sql_text, uint sql_text_len) { TABLE_LIST table_list; TABLE *table; @@ -586,7 +558,7 @@ bool Log_to_csv_event_handler:: need_close= TRUE; - if (sqlt_intact.check(table_list.table, &slow_query_log_table_def)) + if (log_table_intact.check(table_list.table, &slow_query_log_table_def)) goto err; if (table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) || @@ -716,8 +688,9 @@ err: DBUG_RETURN(result); } -int Log_to_csv_event_handler:: - activate_log(THD *thd, uint log_table_type) + +int Log_to_csv_event_handler::activate_log(THD *thd, + enum_log_table_type log_table_type) { TABLE_LIST table_list; TABLE *table; @@ -753,35 +726,18 @@ int Log_to_csv_event_handler:: DBUG_RETURN(result); } -bool Log_to_csv_event_handler:: - log_error(enum loglevel level, const char *format, va_list args) -{ - /* No log table is implemented */ - DBUG_ASSERT(0); - return FALSE; -} - -bool Log_to_file_event_handler:: - log_error(enum loglevel level, const char *format, - va_list args) -{ - return vprint_msg_to_log(level, format, args); -} - -void Log_to_file_event_handler::init_pthread_objects() -{ - mysql_log.init_pthread_objects(); - mysql_slow_log.init_pthread_objects(); -} - -/** Wrapper around MYSQL_LOG::write() for slow log. */ +/** Wrapper around MYSQL_QUERY_LOG::write() for slow log. */ -bool Log_to_file_event_handler:: - log_slow(THD *thd, time_t current_time, time_t query_start_arg, - const char *user_host, uint user_host_len, - ulonglong query_utime, ulonglong lock_utime, bool is_command, - const char *sql_text, uint sql_text_len) +bool Log_to_file_event_handler::log_slow(THD *thd, time_t current_time, + time_t query_start_arg, + const char *user_host, + uint user_host_len, + ulonglong query_utime, + ulonglong lock_utime, + bool is_command, + const char *sql_text, + uint sql_text_len) { Silence_log_table_errors error_handler; thd->push_internal_handler(&error_handler); @@ -795,16 +751,19 @@ bool Log_to_file_event_handler:: /** - Wrapper around MYSQL_LOG::write() for general log. We need it since we + Wrapper around MYSQL_QUERY_LOG::write() for general log. We need it since we want all log event handlers to have the same signature. */ -bool Log_to_file_event_handler:: - log_general(THD *thd, time_t event_time, const char *user_host, - uint user_host_len, my_thread_id thread_id, - const char *command_type, uint command_type_len, - const char *sql_text, uint sql_text_len, - const CHARSET_INFO *client_cs) +bool Log_to_file_event_handler::log_general(THD *thd, time_t event_time, + const char *user_host, + uint user_host_len, + my_thread_id thread_id, + const char *command_type, + uint command_type_len, + const char *sql_text, + uint sql_text_len, + const CHARSET_INFO *client_cs) { Silence_log_table_errors error_handler; thd->push_internal_handler(&error_handler); @@ -826,19 +785,13 @@ bool Log_to_file_event_handler::init() if (opt_log) mysql_log.open_query_log(opt_logname); - is_initialized= TRUE; + is_initialized= true; } - return FALSE; + return false; } -void Log_to_file_event_handler::cleanup() -{ - mysql_log.cleanup(); - mysql_slow_log.cleanup(); -} - void Log_to_file_event_handler::flush() { /* reopen log files */ @@ -848,6 +801,7 @@ void Log_to_file_event_handler::flush() mysql_slow_log.reopen_file(); } + /* Log error with all enabled log event handlers @@ -867,7 +821,7 @@ void Log_to_file_event_handler::flush() bool LOGGER::error_log_print(enum loglevel level, const char *format, va_list args) { - bool error= FALSE; + bool error= false; Log_event_handler **current_handler; /* currently we don't need locking here as there is no error_log table */ @@ -909,6 +863,7 @@ void LOGGER::cleanup_end() Perform basic log initialization: create file-based log handler and init error log. */ + void LOGGER::init_base() { DBUG_ASSERT(inited == 0); @@ -962,7 +917,7 @@ bool LOGGER::flush_logs(THD *thd) /** Close and reopen the slow log (with locks). - + @returns FALSE. */ bool LOGGER::flush_slow_log() @@ -1024,7 +979,6 @@ bool LOGGER::flush_general_log() */ bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length) - { bool error= FALSE; Log_event_handler **current_handler; @@ -1093,6 +1047,7 @@ bool LOGGER::slow_log_print(THD *thd, co return error; } + bool LOGGER::general_log_write(THD *thd, enum enum_server_command command, const char *query, uint query_length) { @@ -1119,7 +1074,7 @@ bool LOGGER::general_log_write(THD *thd, command_name[(uint) command].str, command_name[(uint) command].length, query, query_length); - + while (*current_handler) error|= (*current_handler++)-> log_general(thd, current_time, user_host_buff, @@ -1133,6 +1088,7 @@ bool LOGGER::general_log_write(THD *thd, return error; } + bool LOGGER::general_log_print(THD *thd, enum enum_server_command command, const char *format, va_list args) { @@ -1149,6 +1105,7 @@ bool LOGGER::general_log_print(THD *thd, return general_log_write(thd, command, message_buff, message_buff_len); } + void LOGGER::init_error_log(uint error_log_printer) { if (error_log_printer & LOG_NONE) @@ -1172,6 +1129,7 @@ void LOGGER::init_error_log(uint error_l } } + void LOGGER::init_slow_log(uint slow_log_printer) { if (slow_log_printer & LOG_NONE) @@ -1197,6 +1155,7 @@ void LOGGER::init_slow_log(uint slow_log } } + void LOGGER::init_general_log(uint general_log_printer) { if (general_log_printer & LOG_NONE) @@ -1223,7 +1182,7 @@ void LOGGER::init_general_log(uint gener } -bool LOGGER::activate_log_handler(THD* thd, uint log_type) +bool LOGGER::activate_log_handler(THD* thd, enum_log_table_type log_type) { MYSQL_QUERY_LOG *file_log; bool res= FALSE; @@ -1239,7 +1198,7 @@ bool LOGGER::activate_log_handler(THD* t { /* Error printed by open table in activate_log() */ res= TRUE; - file_log->close(0); + file_log->close(false); } else { @@ -1258,7 +1217,7 @@ bool LOGGER::activate_log_handler(THD* t { /* Error printed by open table in activate_log() */ res= TRUE; - file_log->close(0); + file_log->close(false); } else { @@ -1275,10 +1234,10 @@ bool LOGGER::activate_log_handler(THD* t } -void LOGGER::deactivate_log_handler(THD *thd, uint log_type) +void LOGGER::deactivate_log_handler(THD *thd, enum_log_table_type log_type) { my_bool *tmp_opt= 0; - MYSQL_LOG *file_log= NULL; + MYSQL_QUERY_LOG *file_log= NULL; switch (log_type) { case QUERY_LOG_SLOW: @@ -1297,18 +1256,12 @@ void LOGGER::deactivate_log_handler(THD return; lock_exclusive(); - file_log->close(0); + file_log->close(false); *tmp_opt= FALSE; unlock(); } -/* the parameters are unused for the log tables */ -bool Log_to_csv_event_handler::init() -{ - return 0; -} - int LOGGER::set_handlers(uint error_log_printer, uint slow_log_printer, uint general_log_printer) @@ -1337,6 +1290,7 @@ int LOGGER::set_handlers(uint error_log_ return 0; } + #ifdef _WIN32 static int eventSource = 0; @@ -1374,131 +1328,6 @@ static void setup_windows_event_source() #endif /* _WIN32 */ -/** - Find a unique filename for 'filename.#'. - - Set '#' to the number next to the maximum found in the most - recent log file extension. - - This function will return nonzero if: (i) the generated name - exceeds FN_REFLEN; (ii) if the number of extensions is exhausted; - or (iii) some other error happened while examining the filesystem. - - @return - nonzero if not possible to get unique filename. -*/ - -static int find_uniq_filename(char *name) -{ - uint i; - char buff[FN_REFLEN], ext_buf[FN_REFLEN]; - struct st_my_dir *dir_info; - reg1 struct fileinfo *file_info; - ulong max_found= 0, next= 0, number= 0; - size_t buf_length, length; - char *start, *end; - int error= 0; - DBUG_ENTER("find_uniq_filename"); - - length= dirname_part(buff, name, &buf_length); - start= name + length; - end= strend(start); - - *end='.'; - length= (size_t) (end - start + 1); - - if ((DBUG_EVALUATE_IF("error_unique_log_filename", 1, - !(dir_info= my_dir(buff,MYF(MY_DONT_SORT)))))) - { // This shouldn't happen - strmov(end,".1"); // use name+1 - DBUG_RETURN(1); - } - file_info= dir_info->dir_entry; - for (i= dir_info->number_off_files ; i-- ; file_info++) - { - if (memcmp(file_info->name, start, length) == 0 && - test_if_number(file_info->name+length, &number,0)) - { - set_if_bigger(max_found,(ulong) number); - } - } - my_dirend(dir_info); - - /* check if reached the maximum possible extension number */ - if (max_found == MAX_LOG_UNIQUE_FN_EXT) - { - sql_print_error("Log filename extension number exhausted: %06lu. \ -Please fix this by archiving old logs and \ -updating the index files.", max_found); - error= 1; - goto end; - } - - next= max_found + 1; - if (sprintf(ext_buf, "%06lu", next)<0) - { - error= 1; - goto end; - } - *end++='.'; - - /* - Check if the generated extension size + the file name exceeds the - buffer size used. If one did not check this, then the filename might be - truncated, resulting in error. - */ - if (((strlen(ext_buf) + (end - name)) >= FN_REFLEN)) - { - sql_print_error("Log filename too large: %s%s (%zu). \ -Please fix this by archiving old logs and updating the \ -index files.", name, ext_buf, (strlen(ext_buf) + (end - name))); - error= 1; - goto end; - } - - if (sprintf(end, "%06lu", next)<0) - { - error= 1; - goto end; - } - - /* print warning if reaching the end of available extensions. */ - if ((next > (MAX_LOG_UNIQUE_FN_EXT - LOG_WARN_UNIQUE_FN_EXT_LEFT))) - sql_print_warning("Next log extension: %lu. \ -Remaining log filename extensions: %lu. \ -Please consider archiving some logs.", next, (MAX_LOG_UNIQUE_FN_EXT - next)); - -end: - DBUG_RETURN(error); -} - - -void MYSQL_LOG::init(enum_log_type log_type_arg, - enum cache_type io_cache_type_arg) -{ - DBUG_ENTER("MYSQL_LOG::init"); - log_type= log_type_arg; - io_cache_type= io_cache_type_arg; - DBUG_PRINT("info",("log_type: %d", log_type)); - DBUG_VOID_RETURN; -} - - -bool MYSQL_LOG::init_and_set_log_file_name(const char *log_name, - const char *new_name, - enum_log_type log_type_arg, - enum cache_type io_cache_type_arg) -{ - init(log_type_arg, io_cache_type_arg); - - if (new_name && !strmov(log_file_name, new_name)) - return TRUE; - else if (!new_name && generate_new_name(log_file_name, log_name)) - return TRUE; - - return FALSE; -} - /* Open a (new) log file. @@ -1507,10 +1336,6 @@ bool MYSQL_LOG::init_and_set_log_file_na open() log_name The name of the log to open - log_type_arg The type of the log. E.g. LOG_NORMAL - new_name The new name for the logfile. This is only needed - when the method is used to open the binlog file. - io_cache_type_arg The type of the IO_CACHE to use for this log file DESCRIPTION Open the logfile, init IO_CACHE and write startup messages @@ -1521,21 +1346,18 @@ bool MYSQL_LOG::init_and_set_log_file_na 1 error */ -bool MYSQL_LOG::open( +bool MYSQL_QUERY_LOG::open( #ifdef HAVE_PSI_INTERFACE PSI_file_key log_file_key, #endif - const char *log_name, enum_log_type log_type_arg, - const char *new_name, enum cache_type io_cache_type_arg) + const char *log_name) { char buff[FN_REFLEN]; File file= -1; my_off_t pos= 0; - int open_flags= O_CREAT | O_BINARY; - DBUG_ENTER("MYSQL_LOG::open"); - DBUG_PRINT("enter", ("log_type: %d", (int) log_type_arg)); + DBUG_ENTER("MYSQL_QUERY_LOG::open"); - write_error= 0; + write_error= false; if (!(name= my_strdup(log_name, MYF(MY_WME)))) { @@ -1543,14 +1365,7 @@ bool MYSQL_LOG::open( goto err; } - if (init_and_set_log_file_name(name, new_name, - log_type_arg, io_cache_type_arg)) - goto err; - - if (io_cache_type == SEQ_READ_APPEND) - open_flags |= O_RDWR | O_APPEND; - else - open_flags |= O_WRONLY | (log_type == LOG_BIN ? 0 : O_APPEND); + fn_format(log_file_name, name, mysql_data_home, "", 4); db[0]= 0; @@ -1560,7 +1375,8 @@ bool MYSQL_LOG::open( #endif if ((file= mysql_file_open(log_file_key, - log_file_name, open_flags, + log_file_name, + O_CREAT | O_BINARY | O_WRONLY | O_APPEND, MYF(MY_WME | ME_WAITTANG))) < 0) goto err; @@ -1572,12 +1388,10 @@ bool MYSQL_LOG::open( goto err; } - if (init_io_cache(&log_file, file, IO_SIZE, io_cache_type, pos, 0, - MYF(MY_WME | MY_NABP | - ((log_type == LOG_BIN) ? MY_WAIT_IF_FULL : 0)))) + if (init_io_cache(&log_file, file, IO_SIZE, WRITE_CACHE, pos, 0, + MYF(MY_WME | MY_NABP))) goto err; - if (log_type == LOG_NORMAL) { char *end; int len=my_snprintf(buff, sizeof(buff), "%s, Version: %s (%s). " @@ -1585,24 +1399,24 @@ bool MYSQL_LOG::open( "embedded library\n", my_progname, server_version, MYSQL_COMPILATION_COMMENT #elif _WIN32 - "started with:\nTCP Port: %d, Named Pipe: %s\n", + "started with:\nTCP Port: %d, Named Pipe: %s\n", my_progname, server_version, MYSQL_COMPILATION_COMMENT, mysqld_port, mysqld_unix_port #else - "started with:\nTcp port: %d Unix socket: %s\n", + "started with:\nTcp port: %d Unix socket: %s\n", my_progname, server_version, MYSQL_COMPILATION_COMMENT, mysqld_port, mysqld_unix_port #endif - ); + ); end= strnmov(buff + len, "Time Id Command Argument\n", sizeof(buff) - len); if (my_b_write(&log_file, (uchar*) buff, (uint) (end-buff)) || - flush_io_cache(&log_file)) + flush_io_cache(&log_file)) goto err; } log_state= LOG_OPENED; - DBUG_RETURN(0); + DBUG_RETURN(false); err: sql_print_error("Could not use %s for logging (error %d). \ @@ -1615,50 +1429,26 @@ shutdown the MySQL server and restart it my_free(name); name= NULL; log_state= LOG_CLOSED; - DBUG_RETURN(1); + DBUG_RETURN(true); } -MYSQL_LOG::MYSQL_LOG() - : name(0), write_error(FALSE), inited(FALSE), log_type(LOG_UNKNOWN), - log_state(LOG_CLOSED) -#ifdef HAVE_PSI_INTERFACE - , m_key_LOCK_log(key_LOG_LOCK_log) -#endif -{ - /* - We don't want to initialize LOCK_Log here as such initialization depends on - safe_mutex (when using safe_mutex) which depends on MY_INIT(), which is - called only in main(). Doing initialization here would make it happen - before main(). - */ - memset(&log_file, 0, sizeof(log_file)); -} - -void MYSQL_LOG::init_pthread_objects() -{ - DBUG_ASSERT(inited == 0); - inited= 1; - mysql_mutex_init(m_key_LOCK_log, &LOCK_log, MY_MUTEX_INIT_SLOW); -} /* Close the log file SYNOPSIS close() - exiting Bitmask. For the slow and general logs the only used bit is - LOG_CLOSE_TO_BE_OPENED. This is used if we intend to call - open at once after close. + to_be_reopened This is used if we intend to call + open at once after close. NOTES One can do an open on the object at once after doing a close. The internal structures are not freed until cleanup() is called */ -void MYSQL_LOG::close(uint exiting) +void MYSQL_QUERY_LOG::close(bool to_be_reopened) { // One can't set log_type here! - DBUG_ENTER("MYSQL_LOG::close"); - DBUG_PRINT("enter",("exiting: %d", (int) exiting)); + DBUG_ENTER("MYSQL_QUERY_LOG::close"); if (log_state == LOG_OPENED) { end_io_cache(&log_file); @@ -1666,7 +1456,7 @@ void MYSQL_LOG::close(uint exiting) if (mysql_file_sync(log_file.file, MYF(MY_WME)) && ! write_error) { char errbuf[MYSYS_STRERROR_SIZE]; - write_error= 1; + write_error= true; sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), name, errno, my_strerror(errbuf, sizeof(errbuf), errno)); } @@ -1674,53 +1464,34 @@ void MYSQL_LOG::close(uint exiting) if (mysql_file_close(log_file.file, MYF(MY_WME)) && ! write_error) { char errbuf[MYSYS_STRERROR_SIZE]; - write_error= 1; + write_error= true; sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), name, errno, my_strerror(errbuf, sizeof(errbuf), errno)); } } - log_state= (exiting & LOG_CLOSE_TO_BE_OPENED) ? LOG_TO_BE_OPENED : LOG_CLOSED; + log_state= to_be_reopened ? LOG_TO_BE_OPENED : LOG_CLOSED; my_free(name); name= NULL; DBUG_VOID_RETURN; } + /** This is called only once. */ -void MYSQL_LOG::cleanup() +void MYSQL_QUERY_LOG::cleanup() { - DBUG_ENTER("cleanup"); + DBUG_ENTER("MYSQL_QUERY_LOG::cleanup"); if (inited) { - inited= 0; + inited= false; mysql_mutex_destroy(&LOCK_log); - close(0); + close(false); } DBUG_VOID_RETURN; } -int MYSQL_LOG::generate_new_name(char *new_name, const char *log_name) -{ - fn_format(new_name, log_name, mysql_data_home, "", 4); - if (log_type == LOG_BIN) - { - if (!fn_ext(log_name)[0]) - { - if (find_uniq_filename(new_name)) - { - my_printf_error(ER_NO_UNIQUE_LOGFILE, ER(ER_NO_UNIQUE_LOGFILE), - MYF(ME_FATALERROR), log_name); - sql_print_error(ER(ER_NO_UNIQUE_LOGFILE), log_name); - return 1; - } - } - } - return 0; -} - - /* Reopen the log file @@ -1732,12 +1503,11 @@ int MYSQL_LOG::generate_new_name(char *n and locks LOCK_log mutex */ - void MYSQL_QUERY_LOG::reopen_file() { char *save_name; - DBUG_ENTER("MYSQL_LOG::reopen_file"); + DBUG_ENTER("MYSQL_QUERY_LOG::reopen_file"); if (!is_open()) { DBUG_PRINT("info",("log is closed")); @@ -1747,8 +1517,8 @@ void MYSQL_QUERY_LOG::reopen_file() mysql_mutex_lock(&LOCK_log); save_name= name; - name= 0; // Don't free name - close(LOG_CLOSE_TO_BE_OPENED); + name= NULL; // Don't free name + close(true); /* Note that at this point, log_state != LOG_CLOSED (important for is_open()). @@ -1758,7 +1528,7 @@ void MYSQL_QUERY_LOG::reopen_file() #ifdef HAVE_PSI_INTERFACE m_log_file_key, #endif - save_name, log_type, 0, io_cache_type); + save_name); my_free(save_name); mysql_mutex_unlock(&LOCK_log); @@ -1852,18 +1622,18 @@ bool MYSQL_QUERY_LOG::write(time_t event } mysql_mutex_unlock(&LOCK_log); - return FALSE; + return false; err: if (!write_error) { char errbuf[MYSYS_STRERROR_SIZE]; - write_error= 1; + write_error= true; sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno, my_strerror(errbuf, sizeof(errbuf), errno)); } mysql_mutex_unlock(&LOCK_log); - return TRUE; + return true; } @@ -1902,7 +1672,7 @@ bool MYSQL_QUERY_LOG::write(THD *thd, ti ulonglong lock_utime, bool is_command, const char *sql_text, uint sql_text_len) { - bool error= 0; + bool error= false; DBUG_ENTER("MYSQL_QUERY_LOG::write"); mysql_mutex_lock(&LOCK_log); @@ -2010,11 +1780,11 @@ bool MYSQL_QUERY_LOG::write(THD *thd, ti tmp_errno= errno; if (tmp_errno) { - error= 1; + error= true; if (! write_error) { char errbuf[MYSYS_STRERROR_SIZE]; - write_error= 1; + write_error= true; sql_print_error(ER(ER_ERROR_ON_WRITE), name, error, my_strerror(errbuf, sizeof(errbuf), errno)); } @@ -2030,9 +1800,9 @@ bool MYSQL_QUERY_LOG::write(THD *thd, ti The following should be using fn_format(); We just need to first change fn_format() to cut the file name if it's too long. */ -const char *MYSQL_LOG::generate_name(const char *log_name, - const char *suffix, - bool strip_ext, char *buff) +const char *MYSQL_QUERY_LOG::generate_name(const char *log_name, + const char *suffix, + char *buff) { if (!log_name || !log_name[0]) { @@ -2040,14 +1810,6 @@ const char *MYSQL_LOG::generate_name(con return (const char *) fn_format(buff, buff, "", suffix, MYF(MY_REPLACE_EXT|MY_REPLACE_DIR)); } - // get rid of extension if the log is binary to avoid problems - if (strip_ext) - { - char *p= fn_ext(log_name); - uint length= (uint) (p - log_name); - strmake(buff, log_name, min(length, FN_REFLEN-1)); - return (const char*)buff; - } return log_name; } @@ -2110,6 +1872,7 @@ bool general_log_print(THD *thd, enum en return error; } + bool general_log_write(THD *thd, enum enum_server_command command, const char *query, uint query_length) { @@ -2120,54 +1883,6 @@ bool general_log_write(THD *thd, enum en return FALSE; } -/** - Check if a string is a valid number. - - @param str String to test - @param res Store value here - @param allow_wildcards Set to 1 if we should ignore '%' and '_' - - @note - For the moment the allow_wildcards argument is not used - Should be move to some other file. - - @retval - 1 String is a number - @retval - 0 String is not a number -*/ - -static bool test_if_number(register const char *str, - ulong *res, bool allow_wildcards) -{ - reg2 int flag; - const char *start; - DBUG_ENTER("test_if_number"); - - flag=0; start=str; - while (*str++ == ' ') ; - if (*--str == '-' || *str == '+') - str++; - while (my_isdigit(files_charset_info,*str) || - (allow_wildcards && (*str == wild_many || *str == wild_one))) - { - flag=1; - str++; - } - if (*str == '.') - { - for (str++ ; - my_isdigit(files_charset_info,*str) || - (allow_wildcards && (*str == wild_many || *str == wild_one)) ; - str++, flag=1) ; - } - if (*str != 0 || flag == 0) - DBUG_RETURN(0); - if (res) - *res=atol(start); - DBUG_RETURN(1); /* Number ok */ -} /* test_if_number */ - void sql_perror(const char *message) { @@ -2228,6 +1943,7 @@ bool flush_error_log() return result; } + #ifdef _WIN32 static void print_buffer_to_nt_eventlog(enum loglevel level, char *buff, size_t length, size_t buffLen) @@ -2298,6 +2014,7 @@ static void print_buffer_to_file(enum lo DBUG_VOID_RETURN; } + /** Prints a printf style message to the error log and, under NT, to the Windows event log. @@ -2314,6 +2031,7 @@ static void print_buffer_to_file(enum lo signature to be compatible with other logging routines, which could return an error (e.g. logging to the log tables) */ + int vprint_msg_to_log(enum loglevel level, const char *format, va_list args) { char buff[1024]; @@ -2332,7 +2050,7 @@ int vprint_msg_to_log(enum loglevel leve #endif /* EMBEDDED_LIBRARY */ -void sql_print_error(const char *format, ...) +void sql_print_error(const char *format, ...) { va_list args; DBUG_ENTER("sql_print_error"); @@ -2345,7 +2063,7 @@ void sql_print_error(const char *format, } -void sql_print_warning(const char *format, ...) +void sql_print_warning(const char *format, ...) { va_list args; DBUG_ENTER("sql_print_warning"); @@ -2358,7 +2076,7 @@ void sql_print_warning(const char *forma } -void sql_print_information(const char *format, ...) +void sql_print_information(const char *format, ...) { va_list args; DBUG_ENTER("sql_print_information"); @@ -2662,7 +2380,7 @@ TC_LOG::enum_result TC_LOG_MMAP::commit( threads waiting for a page, but then all these threads will be waiting for a fsync() anyway - If tc_log == MYSQL_LOG then tc_log writes transaction to binlog and + If tc_log == MYSQL_BIN_LOG then tc_log writes transaction to binlog and records XID in a special Xid_log_event. If tc_log = TC_LOG_MMAP then xid is written in a special memory-mapped log. === modified file 'sql/log.h' --- a/sql/log.h 2012-11-06 14:16:49 +0000 +++ b/sql/log.h 2012-11-14 10:15:19 +0000 @@ -20,21 +20,6 @@ #include "handler.h" /* my_xid */ /** - the struct aggregates two paramenters that identify an event - uniquely in scope of communication of a particular master and slave couple. - I.e there can not be 2 events from the same staying connected master which - have the same coordinates. - @note - Such identifier is not yet unique generally as the event originating master - is resetable. Also the crashed master can be replaced with some other. -*/ -typedef struct event_coordinates -{ - char * file_name; // binlog file name (directories stripped) - my_off_t pos; // event's position in the binlog file -} LOG_POS_COORD; - -/** Transaction Coordinator Log. A base abstract class for three different implementations of the @@ -183,160 +168,43 @@ extern TC_LOG *tc_log; extern TC_LOG_MMAP tc_log_mmap; extern TC_LOG_DUMMY tc_log_dummy; -/* log info errors */ -#define LOG_INFO_EOF -1 -#define LOG_INFO_IO -2 -#define LOG_INFO_INVALID -3 -#define LOG_INFO_SEEK -4 -#define LOG_INFO_MEM -6 -#define LOG_INFO_FATAL -7 -#define LOG_INFO_IN_USE -8 -#define LOG_INFO_EMFILE -9 - - -/* bitmap to SQL_LOG::close() */ -#define LOG_CLOSE_INDEX 1 -#define LOG_CLOSE_TO_BE_OPENED 2 -#define LOG_CLOSE_STOP_EVENT 4 - -/* - Maximum unique log filename extension. - Note: setting to 0x7FFFFFFF due to atol windows - overflow/truncate. - */ -#define MAX_LOG_UNIQUE_FN_EXT 0x7FFFFFFF - -/* - Number of warnings that will be printed to error log - before extension number is exhausted. -*/ -#define LOG_WARN_UNIQUE_FN_EXT_LEFT 1000 - -#ifdef HAVE_PSI_INTERFACE -extern PSI_mutex_key key_LOG_INFO_lock; -#endif - -/* - Note that we destroy the lock mutex in the desctructor here. - This means that object instances cannot be destroyed/go out of scope, - until we have reset thd->current_linfo to NULL; - */ -typedef struct st_log_info +/* type of the log table */ +enum enum_log_table_type { - char log_file_name[FN_REFLEN]; - my_off_t index_file_offset, index_file_start_offset; - my_off_t pos; - bool fatal; // if the purge happens to give us a negative offset - mysql_mutex_t lock; - st_log_info() - : index_file_offset(0), index_file_start_offset(0), - pos(0), fatal(0) - { - log_file_name[0] = '\0'; - mysql_mutex_init(key_LOG_INFO_lock, &lock, MY_MUTEX_INIT_FAST); - } - ~st_log_info() { mysql_mutex_destroy(&lock);} -} LOG_INFO; - -/* - Currently we have only 3 kinds of logging functions: old-fashioned - logs, stdout and csv logging routines. -*/ -#define MAX_LOG_HANDLERS_NUM 3 - -/* log event handler flags */ -#define LOG_NONE 1 -#define LOG_FILE 2 -#define LOG_TABLE 4 - -enum enum_log_type { LOG_UNKNOWN, LOG_NORMAL, LOG_BIN }; -enum enum_log_state { LOG_OPENED, LOG_CLOSED, LOG_TO_BE_OPENED }; - -/* - TODO use mmap instead of IO_CACHE for binlog - (mmap+fsync is two times faster than write+fsync) -*/ + NO_LOG_TABLE = 0, + QUERY_LOG_SLOW = 1, + QUERY_LOG_GENERAL = 2 +}; -class MYSQL_LOG +class MYSQL_QUERY_LOG { +private: + static const uint MAX_TIME_SIZE= 32; public: - MYSQL_LOG(); - void init_pthread_objects(); - void cleanup(); - bool open( + MYSQL_QUERY_LOG() + : name(NULL), write_error(false), inited(false), + log_state(LOG_CLOSED), last_time(0) #ifdef HAVE_PSI_INTERFACE - PSI_file_key log_file_key, + ,m_key_LOCK_log(key_LOG_LOCK_log) #endif - const char *log_name, - enum_log_type log_type, - const char *new_name, - enum cache_type io_cache_type_arg); - bool init_and_set_log_file_name(const char *log_name, - const char *new_name, - enum_log_type log_type_arg, - enum cache_type io_cache_type_arg); - void init(enum_log_type log_type_arg, - enum cache_type io_cache_type_arg); - void close(uint exiting); - inline bool is_open() { return log_state != LOG_CLOSED; } - const char *generate_name(const char *log_name, const char *suffix, - bool strip_ext, char *buff); - int generate_new_name(char *new_name, const char *log_name); - protected: - /* LOCK_log is inited by init_pthread_objects() */ - mysql_mutex_t LOCK_log; - char *name; - char log_file_name[FN_REFLEN]; - char time_buff[20], db[NAME_LEN + 1]; - bool write_error, inited; - IO_CACHE log_file; - enum_log_type log_type; - volatile enum_log_state log_state; - enum cache_type io_cache_type; - friend class Log_event; -#ifdef HAVE_PSI_INTERFACE - /** Instrumentation key to use for file io in @c log_file */ - PSI_file_key m_log_file_key; - /** The instrumentation key to use for @ LOCK_log. */ - PSI_mutex_key m_key_LOCK_log; -#endif -}; - - -enum enum_general_log_table_field -{ - GLT_FIELD_EVENT_TIME = 0, - GLT_FIELD_USER_HOST, - GLT_FIELD_THREAD_ID, - GLT_FIELD_SERVER_ID, - GLT_FIELD_COMMAND_TYPE, - GLT_FIELD_ARGUMENT, - GLT_FIELD_COUNT -}; - - -enum enum_slow_query_log_table_field -{ - SQLT_FIELD_START_TIME = 0, - SQLT_FIELD_USER_HOST, - SQLT_FIELD_QUERY_TIME, - SQLT_FIELD_LOCK_TIME, - SQLT_FIELD_ROWS_SENT, - SQLT_FIELD_ROWS_EXAMINED, - SQLT_FIELD_DATABASE, - SQLT_FIELD_LAST_INSERT_ID, - SQLT_FIELD_INSERT_ID, - SQLT_FIELD_SERVER_ID, - SQLT_FIELD_SQL_TEXT, - SQLT_FIELD_THREAD_ID, - SQLT_FIELD_COUNT -}; - - -class MYSQL_QUERY_LOG: public MYSQL_LOG -{ -public: - MYSQL_QUERY_LOG() : last_time(0) {} + { + /* + We don't want to initialize LOCK_Log here as such initialization depends on + safe_mutex (when using safe_mutex) which depends on MY_INIT(), which is + called only in main(). Doing initialization here would make it happen + before main(). + */ + memset(&log_file, 0, sizeof(log_file)); + } + bool is_open() const { return log_state != LOG_CLOSED; } + void close(bool to_be_reopened); + void cleanup(); + void init_pthread_objects() + { + DBUG_ASSERT(inited == false); + inited= true; + mysql_mutex_init(m_key_LOCK_log, &LOCK_log, MY_MUTEX_INIT_SLOW); + } void reopen_file(); bool write(time_t event_time, const char *user_host, uint user_host_len, my_thread_id thread_id, @@ -353,8 +221,7 @@ public: #ifdef HAVE_PSI_INTERFACE key_file_slow_log, #endif - generate_name(log_name, "-slow.log", 0, buf), - LOG_NORMAL, 0, WRITE_CACHE); + generate_name(log_name, "-slow.log", buf)); } bool open_query_log(const char *log_name) { @@ -363,12 +230,36 @@ public: #ifdef HAVE_PSI_INTERFACE key_file_query_log, #endif - generate_name(log_name, ".log", 0, buf), - LOG_NORMAL, 0, WRITE_CACHE); + generate_name(log_name, ".log", buf)); } private: + bool open( +#ifdef HAVE_PSI_INTERFACE + PSI_file_key log_file_key, +#endif + const char *log_name); + const char *generate_name(const char *log_name, const char *suffix, + char *buff); + + enum enum_log_state { LOG_OPENED, LOG_CLOSED, LOG_TO_BE_OPENED }; + +private: + /* LOCK_log is inited by init_pthread_objects() */ + mysql_mutex_t LOCK_log; + char *name; + char log_file_name[FN_REFLEN]; + char db[NAME_LEN + 1]; + bool write_error, inited; + IO_CACHE log_file; + volatile enum_log_state log_state; time_t last_time; +#ifdef HAVE_PSI_INTERFACE + /** Instrumentation key to use for file io in @c log_file */ + PSI_file_key m_log_file_key; + /** The instrumentation key to use for @ LOCK_log. */ + PSI_mutex_key m_key_LOCK_log; +#endif }; class Log_event_handler @@ -393,16 +284,10 @@ public: virtual ~Log_event_handler() {} }; - -int check_if_log_table(size_t db_len, const char *db, size_t table_name_len, - const char *table_name, bool check_if_opened); - class Log_to_csv_event_handler: public Log_event_handler { public: - Log_to_csv_event_handler(); - ~Log_to_csv_event_handler(); - virtual bool init(); + virtual bool init() { return false; } virtual void cleanup(); virtual bool log_slow(THD *thd, time_t current_time, @@ -411,20 +296,22 @@ public: ulonglong lock_utime, bool is_command, const char *sql_text, uint sql_text_len); virtual bool log_error(enum loglevel level, const char *format, - va_list args); + va_list args) + { + /* No log table is implemented */ + DBUG_ASSERT(0); + return false; + } virtual bool log_general(THD *thd, time_t event_time, const char *user_host, uint user_host_len, my_thread_id thread_id, const char *command_type, uint command_type_len, const char *sql_text, uint sql_text_len, const CHARSET_INFO *client_cs); - int activate_log(THD *thd, uint log_type); + int activate_log(THD *thd, enum_log_table_type log_type); }; - -/* type of the log table */ -#define QUERY_LOG_SLOW 1 -#define QUERY_LOG_GENERAL 2 +int vprint_msg_to_log(enum loglevel level, const char *format, va_list args); class Log_to_file_event_handler: public Log_event_handler { @@ -435,7 +322,11 @@ public: Log_to_file_event_handler(): is_initialized(FALSE) {} virtual bool init(); - virtual void cleanup(); + virtual void cleanup() + { + mysql_log.cleanup(); + mysql_slow_log.cleanup(); + } virtual bool log_slow(THD *thd, time_t current_time, time_t query_start_arg, const char *user_host, @@ -443,22 +334,43 @@ public: ulonglong lock_utime, bool is_command, const char *sql_text, uint sql_text_len); virtual bool log_error(enum loglevel level, const char *format, - va_list args); + va_list args) + { + return vprint_msg_to_log(level, format, args); + } virtual bool log_general(THD *thd, time_t event_time, const char *user_host, uint user_host_len, my_thread_id thread_id, const char *command_type, uint command_type_len, const char *sql_text, uint sql_text_len, const CHARSET_INFO *client_cs); void flush(); - void init_pthread_objects(); + void init_pthread_objects() + { + mysql_log.init_pthread_objects(); + mysql_slow_log.init_pthread_objects(); + } MYSQL_QUERY_LOG *get_mysql_slow_log() { return &mysql_slow_log; } MYSQL_QUERY_LOG *get_mysql_log() { return &mysql_log; } }; +/* log event handler flags */ +static const uint LOG_NONE= 1; +static const uint LOG_FILE= 2; +static const uint LOG_TABLE= 4; + + /* Class which manages slow, general and error log event handlers */ class LOGGER { + /* + Currently we have only 3 kinds of logging functions: old-fashioned + logs, stdout and csv logging routines. + */ + static const uint MAX_LOG_HANDLERS_NUM= 3; + /* max size of the log message */ + static const uint MAX_LOG_BUFFER_SIZE= 1024; + mysql_rwlock_t LOCK_logger; /* flag to check whether logger mutex is initialized */ uint inited; @@ -471,18 +383,22 @@ class LOGGER Log_event_handler *error_log_handler_list[MAX_LOG_HANDLERS_NUM + 1]; Log_event_handler *slow_log_handler_list[MAX_LOG_HANDLERS_NUM + 1]; Log_event_handler *general_log_handler_list[MAX_LOG_HANDLERS_NUM + 1]; - public: - bool is_log_tables_initialized; +private: + void init_error_log(uint error_log_printer); + void init_slow_log(uint slow_log_printer); + void init_general_log(uint general_log_printer); + +public: LOGGER() : inited(0), table_log_handler(NULL), file_log_handler(NULL), is_log_tables_initialized(FALSE) {} void lock_shared() { mysql_rwlock_rdlock(&LOCK_logger); } void lock_exclusive() { mysql_rwlock_wrlock(&LOCK_logger); } void unlock() { mysql_rwlock_unlock(&LOCK_logger); } - bool is_log_table_enabled(uint log_table_type); + bool is_log_table_enabled(enum_log_table_type log_table_type); bool log_command(THD *thd, enum enum_server_command command); /* @@ -512,45 +428,34 @@ public: int set_handlers(uint error_log_printer, uint slow_log_printer, uint general_log_printer); - void init_error_log(uint error_log_printer); - void init_slow_log(uint slow_log_printer); - void init_general_log(uint general_log_printer); - void deactivate_log_handler(THD* thd, uint log_type); - bool activate_log_handler(THD* thd, uint log_type); + void deactivate_log_handler(THD* thd, enum_log_table_type log_type); + bool activate_log_handler(THD* thd, enum_log_table_type log_type); MYSQL_QUERY_LOG *get_slow_log_file_handler() const - { + { if (file_log_handler) return file_log_handler->get_mysql_slow_log(); return NULL; } MYSQL_QUERY_LOG *get_log_file_handler() const - { + { if (file_log_handler) return file_log_handler->get_mysql_log(); return NULL; } + void set_log_output(uint log_printer) + { + lock_exclusive(); + init_slow_log(log_printer); + init_general_log(log_printer); + unlock(); + } }; -enum enum_binlog_row_image { - /** PKE in the before image and changed columns in the after image */ - BINLOG_ROW_IMAGE_MINIMAL= 0, - /** Whenever possible, before and after image contain all columns except blobs. */ - BINLOG_ROW_IMAGE_NOBLOB= 1, - /** All columns in both before and after image. */ - BINLOG_ROW_IMAGE_FULL= 2 -}; - -enum enum_binlog_format { - BINLOG_FORMAT_MIXED= 0, ///< statement if safe, otherwise row - autodetected - BINLOG_FORMAT_STMT= 1, ///< statement-based - BINLOG_FORMAT_ROW= 2, ///< row-based - BINLOG_FORMAT_UNSPEC=3 ///< thd_binlog_format() returns it when binlog is closed -}; - -int query_error_code(THD *thd, bool not_killed); -uint purge_log_get_error_code(int res); +enum_log_table_type check_if_log_table(size_t db_len, const char *db, + size_t table_name_len, + const char *table_name, + bool check_if_opened); -int vprint_msg_to_log(enum loglevel level, const char *format, va_list args); void sql_print_error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2); void sql_print_warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2); void sql_print_information(const char *format, ...) === modified file 'sql/mysqld.cc' --- a/sql/mysqld.cc 2012-11-08 10:05:03 +0000 +++ b/sql/mysqld.cc 2012-11-14 10:15:19 +0000 @@ -4669,7 +4669,7 @@ a file name for --log-bin-index option", char buf[FN_REFLEN]; const char *ln; - ln= mysql_bin_log.generate_name(opt_bin_logname, "-bin", 1, buf); + ln= mysql_bin_log.generate_name(opt_bin_logname, "-bin", buf); if (!opt_bin_logname && !opt_binlog_index_name) { /* @@ -4903,7 +4903,7 @@ a file name for --log-bin-index option", mysql_bin_log.set_previous_gtid_set( const_cast(gtid_state->get_logged_gtids())); if (mysql_bin_log.open_binlog(opt_bin_logname, 0, - WRITE_CACHE, max_binlog_size, false, + max_binlog_size, false, true/*need_lock_index=true*/, true/*need_sid_lock=true*/, NULL)) === modified file 'sql/rpl_rli.cc' --- a/sql/rpl_rli.cc 2012-11-06 14:16:49 +0000 +++ b/sql/rpl_rli.cc 2012-11-14 10:15:19 +0000 @@ -75,7 +75,7 @@ Relay_log_info::Relay_log_info(bool is_s , param_id ), replicate_same_server_id(::replicate_same_server_id), - cur_log_fd(-1), relay_log(&sync_relaylog_period), + cur_log_fd(-1), relay_log(&sync_relaylog_period, SEQ_READ_APPEND), is_relay_log_recovery(is_slave_recovery), save_temporary_tables(0), cur_log_old_open_count(0), group_relay_log_pos(0), event_relay_log_pos(0), @@ -1727,7 +1727,7 @@ a file name for --relay-log-index option const char *ln; static bool name_warning_sent= 0; ln= relay_log.generate_name(opt_relay_logname, "-relay-bin", - 1, buf); + buf); /* We send the warning only at startup, not after every RESET SLAVE */ if (!opt_relay_logname && !opt_relaylog_index_name && !name_warning_sent) { @@ -1781,7 +1781,7 @@ a file name for --relay-log-index option note, that if open() fails, we'll still have index file open but a destructor will take care of that */ - if (relay_log.open_binlog(ln, 0, SEQ_READ_APPEND, + if (relay_log.open_binlog(ln, 0, (max_relay_log_size ? max_relay_log_size : max_binlog_size), true, true/*need_lock_index=true*/, === modified file 'sql/rpl_tblmap.h' --- a/sql/rpl_tblmap.h 2011-09-07 10:08:09 +0000 +++ b/sql/rpl_tblmap.h 2012-11-14 10:15:19 +0000 @@ -26,6 +26,22 @@ void free_table_map_log_event(TABLE *tab #endif +/** + the struct aggregates two paramenters that identify an event + uniquely in scope of communication of a particular master and slave couple. + I.e there can not be 2 events from the same staying connected master which + have the same coordinates. + @note + Such identifier is not yet unique generally as the event originating master + is resetable. Also the crashed master can be replaced with some other. +*/ +typedef struct event_coordinates +{ + char * file_name; // binlog file name (directories stripped) + my_off_t pos; // event's position in the binlog file +} LOG_POS_COORD; + + /* CLASS table_mapping === modified file 'sql/sql_alter.cc' --- a/sql/sql_alter.cc 2012-10-25 13:34:04 +0000 +++ b/sql/sql_alter.cc 2012-11-14 10:15:19 +0000 @@ -340,11 +340,12 @@ bool Sql_cmd_discard_import_tablespace:: it is the case. TODO: this design is obsolete and will be removed. */ - int table_kind= check_if_log_table(table_list->db_length, table_list->db, - table_list->table_name_length, - table_list->table_name, false); + enum_log_table_type table_kind= + check_if_log_table(table_list->db_length, table_list->db, + table_list->table_name_length, + table_list->table_name, false); - if (table_kind) + if (table_kind != NO_LOG_TABLE) { /* Disable alter of enabled log tables */ if (logger.is_log_table_enabled(table_kind)) === modified file 'sql/sql_class.h' --- a/sql/sql_class.h 2012-11-08 23:03:17 +0000 +++ b/sql/sql_class.h 2012-11-14 10:15:19 +0000 @@ -81,6 +81,7 @@ class Rows_log_event; class Sroutine_hash_entry; class User_level_lock; class user_var_entry; +typedef struct st_log_info LOG_INFO; enum enum_ha_read_modes { RFIRST, RNEXT, RPREV, RLAST, RKEY, RNEXT_SAME }; @@ -94,6 +95,20 @@ enum enum_slave_type_conversions { SLAVE enum enum_slave_rows_search_algorithms { SLAVE_ROWS_TABLE_SCAN = (1U << 0), SLAVE_ROWS_INDEX_SCAN = (1U << 1), SLAVE_ROWS_HASH_SCAN = (1U << 2)}; +enum enum_binlog_row_image { + /** PKE in the before image and changed columns in the after image */ + BINLOG_ROW_IMAGE_MINIMAL= 0, + /** Whenever possible, before and after image contain all columns except blobs. */ + BINLOG_ROW_IMAGE_NOBLOB= 1, + /** All columns in both before and after image. */ + BINLOG_ROW_IMAGE_FULL= 2 +}; +enum enum_binlog_format { + BINLOG_FORMAT_MIXED= 0, ///< statement if safe, otherwise row - autodetected + BINLOG_FORMAT_STMT= 1, ///< statement-based + BINLOG_FORMAT_ROW= 2, ///< row-based + BINLOG_FORMAT_UNSPEC=3 ///< thd_binlog_format() returns it when binlog is closed +}; enum enum_mark_columns { MARK_COLUMNS_NONE, MARK_COLUMNS_READ, MARK_COLUMNS_WRITE}; === modified file 'sql/sql_table.cc' --- a/sql/sql_table.cc 2012-11-07 12:05:17 +0000 +++ b/sql/sql_table.cc 2012-11-14 10:15:19 +0000 @@ -7487,11 +7487,12 @@ bool mysql_alter_table(THD *thd,char *ne it is the case. TODO: this design is obsolete and will be removed. */ - int table_kind= check_if_log_table(table_list->db_length, table_list->db, - table_list->table_name_length, - table_list->table_name, false); + enum_log_table_type table_kind= + check_if_log_table(table_list->db_length, table_list->db, + table_list->table_name_length, + table_list->table_name, false); - if (table_kind) + if (table_kind != NO_LOG_TABLE) { /* Disable alter of enabled log tables */ if (logger.is_log_table_enabled(table_kind)) === modified file 'sql/sys_vars.cc' --- a/sql/sys_vars.cc 2012-11-07 16:54:50 +0000 +++ b/sql/sys_vars.cc 2012-11-14 10:15:19 +0000 @@ -3764,7 +3764,7 @@ static bool fix_log_state(sys_var *self, { bool res; my_bool *UNINIT_VAR(newvalptr), newval, UNINIT_VAR(oldval); - uint UNINIT_VAR(log_type); + enum_log_table_type log_type= NO_LOG_TABLE; if (self == &Sys_general_log) { @@ -3805,10 +3805,7 @@ static bool check_not_empty_set(sys_var } static bool fix_log_output(sys_var *self, THD *thd, enum_var_type type) { - logger.lock_exclusive(); - logger.init_slow_log(log_output_options); - logger.init_general_log(log_output_options); - logger.unlock(); + logger.set_log_output(log_output_options); return false; } No bundle (reason: useless for push emails).