27 #include "my_global.h"
31 #include "sql_delete.h"
32 #include "sql_parse.h"
36 #include "sql_audit.h"
51 #define MAX_LOG_BUFFER_SIZE 1024
52 #define MAX_TIME_SIZE 32
58 { C_STRING_WITH_LEN(
"start_time") },
59 { C_STRING_WITH_LEN(
"timestamp") },
63 { C_STRING_WITH_LEN(
"user_host") },
64 { C_STRING_WITH_LEN(
"mediumtext") },
65 { C_STRING_WITH_LEN(
"utf8") }
68 { C_STRING_WITH_LEN(
"query_time") },
69 { C_STRING_WITH_LEN(
"time") },
73 { C_STRING_WITH_LEN(
"lock_time") },
74 { C_STRING_WITH_LEN(
"time") },
78 { C_STRING_WITH_LEN(
"rows_sent") },
79 { C_STRING_WITH_LEN(
"int(11)") },
83 { C_STRING_WITH_LEN(
"rows_examined") },
84 { C_STRING_WITH_LEN(
"int(11)") },
88 { C_STRING_WITH_LEN(
"db") },
89 { C_STRING_WITH_LEN(
"varchar(512)") },
90 { C_STRING_WITH_LEN(
"utf8") }
93 { C_STRING_WITH_LEN(
"last_insert_id") },
94 { C_STRING_WITH_LEN(
"int(11)") },
98 { C_STRING_WITH_LEN(
"insert_id") },
99 { C_STRING_WITH_LEN(
"int(11)") },
103 { C_STRING_WITH_LEN(
"server_id") },
104 { C_STRING_WITH_LEN(
"int(10) unsigned") },
108 { C_STRING_WITH_LEN(
"sql_text") },
109 { C_STRING_WITH_LEN(
"mediumtext") },
110 { C_STRING_WITH_LEN(
"utf8") }
113 { C_STRING_WITH_LEN(
"thread_id") },
114 { C_STRING_WITH_LEN(
"bigint(21) unsigned") },
120 slow_query_log_table_def= {SQLT_FIELD_COUNT, slow_query_log_table_fields};
125 void report_error(uint,
const char *
fmt, ...)
129 error_log_print(ERROR_LEVEL, fmt, args);
141 { C_STRING_WITH_LEN(
"event_time") },
142 { C_STRING_WITH_LEN(
"timestamp") },
146 { C_STRING_WITH_LEN(
"user_host") },
147 { C_STRING_WITH_LEN(
"mediumtext") },
148 { C_STRING_WITH_LEN(
"utf8") }
151 { C_STRING_WITH_LEN(
"thread_id") },
152 { C_STRING_WITH_LEN(
"bigint(21) unsigned") },
156 { C_STRING_WITH_LEN(
"server_id") },
157 { C_STRING_WITH_LEN(
"int(10) unsigned") },
161 { C_STRING_WITH_LEN(
"command_type") },
162 { C_STRING_WITH_LEN(
"varchar(64)") },
163 { C_STRING_WITH_LEN(
"utf8") }
166 { C_STRING_WITH_LEN(
"argument") },
167 { C_STRING_WITH_LEN(
"mediumtext") },
168 { C_STRING_WITH_LEN(
"utf8") }
173 general_log_table_def= {GLT_FIELD_COUNT, general_log_table_fields};
178 void report_error(uint,
const char *
fmt, ...)
182 error_log_print(ERROR_LEVEL, fmt, args);
192 static bool test_if_number(
const char *str,
193 ulong *res,
bool allow_wildcards);
210 case LOG_INFO_EOF: errcode= ER_UNKNOWN_TARGET_BINLOG;
break;
211 case LOG_INFO_IO: errcode= ER_IO_ERR_LOG_INDEX_READ;
break;
212 case LOG_INFO_INVALID:errcode= ER_BINLOG_PURGE_PROHIBITED;
break;
213 case LOG_INFO_SEEK: errcode= ER_FSEEK_FAIL;
break;
214 case LOG_INFO_MEM: errcode= ER_OUT_OF_RESOURCES;
break;
215 case LOG_INFO_FATAL: errcode= ER_BINLOG_PURGE_FATAL_ERR;
break;
216 case LOG_INFO_IN_USE: errcode= ER_LOG_IN_USE;
break;
217 case LOG_INFO_EMFILE: errcode= ER_BINLOG_PURGE_EMFILE;
break;
218 default: errcode= ER_LOG_PURGE_UNKNOWN_ERR;
break;
233 char m_message[MYSQL_ERRMSG_SIZE];
242 virtual bool handle_condition(THD *thd,
244 const char* sql_state,
245 Sql_condition::enum_warning_level
level,
248 const char *
message()
const {
return m_message; }
252 Silence_log_table_errors::handle_condition(THD *,
255 Sql_condition::enum_warning_level,
260 strmake(m_message, msg,
sizeof(m_message)-1);
264 sql_print_message_func sql_print_message_handlers[3] =
266 sql_print_information,
285 strmake(buff, name, FN_REFLEN-5);
286 return fn_format(buff, buff, mysql_real_data_home, log_ext,
287 MYF(MY_UNPACK_FILENAME|MY_REPLACE_EXT));
290 bool LOGGER::is_log_table_enabled(uint log_table_type)
292 switch (log_table_type) {
294 return (table_log_handler != NULL) && opt_slow_log;
295 case QUERY_LOG_GENERAL:
296 return (table_log_handler != NULL) && opt_log ;
305 int check_if_log_table(
size_t db_len,
const char *db,
size_t table_name_len,
309 !(lower_case_table_names ?
310 my_strcasecmp(system_charset_info, db,
"mysql") :
311 strcmp(db,
"mysql")))
313 if (table_name_len == 11 && !(lower_case_table_names ?
314 my_strcasecmp(system_charset_info,
315 table_name,
"general_log") :
316 strcmp(table_name,
"general_log")))
318 if (!check_if_opened || logger.is_log_table_enabled(QUERY_LOG_GENERAL))
319 return QUERY_LOG_GENERAL;
323 if (table_name_len == 8 && !(lower_case_table_names ?
324 my_strcasecmp(system_charset_info, table_name,
"slow_log") :
325 strcmp(table_name,
"slow_log")))
327 if (!check_if_opened || logger.is_log_table_enabled(QUERY_LOG_SLOW))
328 return QUERY_LOG_SLOW;
336 Log_to_csv_event_handler::Log_to_csv_event_handler()
341 Log_to_csv_event_handler::~Log_to_csv_event_handler()
346 void Log_to_csv_event_handler::cleanup()
348 logger.is_log_tables_initialized= FALSE;
385 uint user_host_len, my_thread_id thread_id,
386 const char *command_type, uint command_type_len,
387 const char *sql_text, uint sql_text_len,
393 bool need_close= FALSE;
394 bool need_pop= FALSE;
395 bool need_rnd_end= FALSE;
398 Open_tables_backup open_tables_backup;
399 ulonglong save_thd_options;
400 bool save_time_zone_used;
406 save_time_zone_used= thd->time_zone_used;
408 save_thd_options= thd->variables.option_bits;
409 thd->variables.option_bits&= ~OPTION_BIN_LOG;
411 table_list.
init_one_table(MYSQL_SCHEMA_NAME.str, MYSQL_SCHEMA_NAME.length,
412 GENERAL_LOG_NAME.str, GENERAL_LOG_NAME.length,
413 GENERAL_LOG_NAME.str,
414 TL_WRITE_CONCURRENT_INSERT);
427 thd->push_internal_handler(& error_handler);
430 if (!(table=
open_log_table(thd, &table_list, &open_tables_backup)))
435 if (glt_intact.
check(table_list.table, &general_log_table_def))
438 if (table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) ||
445 table->next_number_field= table->found_next_number_field;
458 if (table->s->fields < 6)
461 DBUG_ASSERT(table->field[GLT_FIELD_EVENT_TIME]->type() == MYSQL_TYPE_TIMESTAMP);
465 if (table->field[GLT_FIELD_USER_HOST]->store(user_host, user_host_len,
467 table->field[GLT_FIELD_THREAD_ID]->store((longlong) thread_id, TRUE) ||
468 table->field[GLT_FIELD_SERVER_ID]->store((longlong) server_id, TRUE) ||
469 table->field[GLT_FIELD_COMMAND_TYPE]->store(command_type,
470 command_type_len, client_cs))
477 table->field[GLT_FIELD_ARGUMENT]->flags|= FIELDFLAG_HEX_ESCAPE;
478 if (table->field[GLT_FIELD_ARGUMENT]->store(sql_text, sql_text_len,
483 table->field[GLT_FIELD_USER_HOST]->set_notnull();
484 table->field[GLT_FIELD_THREAD_ID]->set_notnull();
485 table->field[GLT_FIELD_SERVER_ID]->set_notnull();
486 table->field[GLT_FIELD_COMMAND_TYPE]->set_notnull();
487 table->field[GLT_FIELD_ARGUMENT]->set_notnull();
490 for (field_index= GLT_FIELD_COUNT ;
491 field_index < table->s->fields ;
494 table->field[field_index]->set_default();
498 if (table->file->ha_write_row(table->record[0]))
504 if (result && !thd->killed)
505 sql_print_error(
"Failed to write to mysql.general_log: %s",
506 error_handler.message());
511 table->file->ha_release_auto_increment();
514 thd->pop_internal_handler();
518 thd->variables.option_bits= save_thd_options;
519 thd->time_zone_used= save_time_zone_used;
553 bool Log_to_csv_event_handler::
554 log_slow(THD *thd, time_t current_time, time_t query_start_arg,
555 const char *user_host, uint user_host_len,
556 ulonglong query_utime, ulonglong lock_utime,
bool is_command,
557 const char *sql_text, uint sql_text_len)
562 bool need_close= FALSE;
563 bool need_rnd_end= FALSE;
565 Open_tables_backup open_tables_backup;
566 const CHARSET_INFO *client_cs= thd->variables.character_set_client;
567 bool save_time_zone_used;
568 DBUG_ENTER(
"Log_to_csv_event_handler::log_slow");
570 thd->push_internal_handler(& error_handler);
575 save_time_zone_used= thd->time_zone_used;
577 table_list.
init_one_table(MYSQL_SCHEMA_NAME.str, MYSQL_SCHEMA_NAME.length,
578 SLOW_LOG_NAME.str, SLOW_LOG_NAME.length,
580 TL_WRITE_CONCURRENT_INSERT);
582 if (!(table=
open_log_table(thd, &table_list, &open_tables_backup)))
587 if (sqlt_intact.
check(table_list.table, &slow_query_log_table_def))
590 if (table->file->extra(HA_EXTRA_MARK_AS_LOG_TABLE) ||
597 table->next_number_field= table->found_next_number_field;
599 restore_record(table, s->default_values);
602 DBUG_ASSERT(table->field[SQLT_FIELD_START_TIME]->type() == MYSQL_TYPE_TIMESTAMP);
604 if (table->field[SQLT_FIELD_USER_HOST]->store(user_host, user_host_len,
610 longlong query_time= (longlong) (query_utime/1000000);
611 longlong lock_time= (longlong) (lock_utime/1000000);
621 calc_time_from_sec(&t, min<long>(query_time, (longlong) TIME_MAX_VALUE_SECONDS), 0);
622 if (table->field[SQLT_FIELD_QUERY_TIME]->
store_time(&t))
625 calc_time_from_sec(&t, min<long>(lock_time, (longlong) TIME_MAX_VALUE_SECONDS), 0);
626 if (table->field[SQLT_FIELD_LOCK_TIME]->
store_time(&t))
629 if (table->field[SQLT_FIELD_ROWS_SENT]->store((longlong) thd->get_sent_row_count(), TRUE))
632 if (table->field[SQLT_FIELD_ROWS_EXAMINED]->store((longlong) thd->get_examined_row_count(), TRUE))
637 table->field[SQLT_FIELD_QUERY_TIME]->set_null();
638 table->field[SQLT_FIELD_LOCK_TIME]->set_null();
639 table->field[SQLT_FIELD_ROWS_SENT]->set_null();
640 table->field[SQLT_FIELD_ROWS_EXAMINED]->set_null();
645 if (table->field[SQLT_FIELD_DATABASE]->store(thd->db, thd->db_length,
648 table->field[SQLT_FIELD_DATABASE]->set_notnull();
651 if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt)
654 field[SQLT_FIELD_LAST_INSERT_ID]->store((longlong)
655 thd->first_successful_insert_id_in_prev_stmt_for_binlog,
658 table->field[SQLT_FIELD_LAST_INSERT_ID]->set_notnull();
667 if (thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements() > 0)
670 field[SQLT_FIELD_INSERT_ID]->store((longlong)
671 thd->auto_inc_intervals_in_cur_stmt_for_binlog.minimum(), TRUE))
673 table->field[SQLT_FIELD_INSERT_ID]->set_notnull();
676 if (table->field[SQLT_FIELD_SERVER_ID]->store((longlong) server_id, TRUE))
678 table->field[SQLT_FIELD_SERVER_ID]->set_notnull();
685 if (table->field[SQLT_FIELD_SQL_TEXT]->store(sql_text, sql_text_len,
689 if (table->field[SQLT_FIELD_THREAD_ID]->store((longlong) thd->thread_id,
694 if (table->file->ha_write_row(table->record[0]))
700 thd->pop_internal_handler();
702 if (result && !thd->killed)
703 sql_print_error(
"Failed to write to mysql.slow_log: %s",
704 error_handler.message());
709 table->file->ha_release_auto_increment();
713 thd->time_zone_used= save_time_zone_used;
717 int Log_to_csv_event_handler::
718 activate_log(THD *thd, uint log_table_type)
724 Open_tables_backup open_tables_backup;
726 DBUG_ENTER(
"Log_to_csv_event_handler::activate_log");
728 if (log_table_type == QUERY_LOG_GENERAL)
730 log_name= &GENERAL_LOG_NAME;
734 DBUG_ASSERT(log_table_type == QUERY_LOG_SLOW);
736 log_name= &SLOW_LOG_NAME;
738 table_list.
init_one_table(MYSQL_SCHEMA_NAME.str, MYSQL_SCHEMA_NAME.length,
739 log_name->str, log_name->length, log_name->str,
740 TL_WRITE_CONCURRENT_INSERT);
754 bool Log_to_csv_event_handler::
755 log_error(
enum loglevel
level,
const char *format, va_list args)
762 bool Log_to_file_event_handler::
763 log_error(
enum loglevel
level,
const char *format,
769 void Log_to_file_event_handler::init_pthread_objects()
771 mysql_log.init_pthread_objects();
772 mysql_slow_log.init_pthread_objects();
779 log_slow(THD *thd, time_t current_time, time_t query_start_arg,
780 const char *user_host, uint user_host_len,
781 ulonglong query_utime, ulonglong lock_utime,
bool is_command,
782 const char *sql_text, uint sql_text_len)
785 thd->push_internal_handler(&error_handler);
786 bool retval= mysql_slow_log.write(thd, current_time, query_start_arg,
787 user_host, user_host_len,
788 query_utime, lock_utime, is_command,
789 sql_text, sql_text_len);
790 thd->pop_internal_handler();
802 uint user_host_len, my_thread_id thread_id,
803 const char *command_type, uint command_type_len,
804 const char *sql_text, uint sql_text_len,
808 thd->push_internal_handler(&error_handler);
809 bool retval= mysql_log.write(event_time, user_host, user_host_len,
810 thread_id, command_type, command_type_len,
811 sql_text, sql_text_len);
812 thd->pop_internal_handler();
817 bool Log_to_file_event_handler::init()
822 mysql_slow_log.open_slow_log(opt_slow_logname);
825 mysql_log.open_query_log(opt_logname);
827 is_initialized= TRUE;
834 void Log_to_file_event_handler::cleanup()
840 void Log_to_file_event_handler::flush()
844 mysql_log.reopen_file();
846 mysql_slow_log.reopen_file();
865 bool LOGGER::error_log_print(
enum loglevel
level,
const char *format,
872 for (current_handler= error_log_handler_list ; *current_handler ;)
873 error= (*current_handler++)->log_error(level, format, args) || error;
879 void LOGGER::cleanup_base()
881 DBUG_ASSERT(inited == 1);
883 if (table_log_handler)
885 table_log_handler->cleanup();
886 delete table_log_handler;
887 table_log_handler= NULL;
889 if (file_log_handler)
890 file_log_handler->cleanup();
894 void LOGGER::cleanup_end()
896 DBUG_ASSERT(inited == 1);
897 if (file_log_handler)
899 delete file_log_handler;
900 file_log_handler=NULL;
912 DBUG_ASSERT(inited == 0);
920 if (!file_log_handler)
924 init_error_log(LOG_FILE);
926 file_log_handler->init_pthread_objects();
931 void LOGGER::init_log_tables()
933 if (!table_log_handler)
936 if (!is_log_tables_initialized &&
937 !table_log_handler->init() && !file_log_handler->init())
938 is_log_tables_initialized= TRUE;
942 bool LOGGER::flush_logs(THD *thd)
950 logger.lock_exclusive();
953 file_log_handler->flush();
972 logger.lock_exclusive();
976 file_log_handler->get_mysql_slow_log()->reopen_file();
996 logger.lock_exclusive();
1000 file_log_handler->get_mysql_log()->reopen_file();
1024 bool LOGGER::slow_log_print(THD *thd,
const char *
query, uint query_length)
1029 bool is_command= FALSE;
1030 char user_host_buff[MAX_USER_HOST_SIZE + 1];
1031 Security_context *sctx= thd->security_ctx;
1032 uint user_host_len= 0;
1033 ulonglong query_utime, lock_utime, current_utime;
1035 DBUG_ASSERT(thd->enable_slow_log);
1040 if (*slow_log_handler_list)
1042 time_t current_time;
1045 if (thd->slave_thread && !opt_log_slow_slave_statements)
1056 user_host_len= (strxnmov(user_host_buff, MAX_USER_HOST_SIZE,
1057 sctx->priv_user ? sctx->priv_user :
"",
"[",
1058 sctx->user ? sctx->user :
"",
"] @ ",
1059 sctx->get_host()->length() ?
1060 sctx->get_host()->ptr() :
"",
" [",
1061 sctx->get_ip()->length() ? sctx->get_ip()->ptr() :
1062 "",
"]", NullS) - user_host_buff);
1065 current_utime= thd->current_utime();
1066 current_time= my_time_possible_from_micro(current_utime);
1067 if (thd->start_utime)
1069 query_utime= (current_utime - thd->start_utime);
1070 lock_utime= (thd->utime_after_lock - thd->start_utime);
1074 query_utime= lock_utime= 0;
1080 query= command_name[thd->get_command()].str;
1081 query_length= command_name[thd->get_command()].length;
1084 for (current_handler= slow_log_handler_list; *current_handler ;)
1085 error= (*current_handler++)->log_slow(thd, current_time,
1086 thd->start_time.tv_sec,
1087 user_host_buff, user_host_len,
1088 query_utime, lock_utime, is_command,
1089 query, query_length) || error;
1096 bool LOGGER::general_log_write(THD *thd,
enum enum_server_command command,
1097 const char *query, uint query_length)
1101 char user_host_buff[MAX_USER_HOST_SIZE + 1];
1102 uint user_host_len= 0;
1103 time_t current_time;
1113 user_host_len= make_user_name(thd, user_host_buff);
1115 current_time= my_time(0);
1117 mysql_audit_general_log(thd, current_time,
1118 user_host_buff, user_host_len,
1119 command_name[(uint) command].str,
1120 command_name[(uint) command].length,
1121 query, query_length);
1123 while (*current_handler)
1124 error|= (*current_handler++)->
1125 log_general(thd, current_time, user_host_buff,
1126 user_host_len, thd->thread_id,
1127 command_name[(uint) command].str,
1128 command_name[(uint) command].length,
1129 query, query_length,
1130 thd->variables.character_set_client) || error;
1136 bool LOGGER::general_log_print(THD *thd,
enum enum_server_command command,
1137 const char *format, va_list args)
1139 uint message_buff_len= 0;
1140 char message_buff[MAX_LOG_BUFFER_SIZE];
1144 message_buff_len= my_vsnprintf(message_buff,
sizeof(message_buff),
1147 message_buff[0]=
'\0';
1149 return general_log_write(thd, command, message_buff, message_buff_len);
1152 void LOGGER::init_error_log(uint error_log_printer)
1154 if (error_log_printer & LOG_NONE)
1156 error_log_handler_list[0]= 0;
1160 switch (error_log_printer) {
1162 error_log_handler_list[0]= file_log_handler;
1163 error_log_handler_list[1]= 0;
1169 case LOG_TABLE|LOG_FILE:
1175 void LOGGER::init_slow_log(uint slow_log_printer)
1177 if (slow_log_printer & LOG_NONE)
1179 slow_log_handler_list[0]= 0;
1183 switch (slow_log_printer) {
1185 slow_log_handler_list[0]= file_log_handler;
1186 slow_log_handler_list[1]= 0;
1189 slow_log_handler_list[0]= table_log_handler;
1190 slow_log_handler_list[1]= 0;
1192 case LOG_TABLE|LOG_FILE:
1193 slow_log_handler_list[0]= file_log_handler;
1194 slow_log_handler_list[1]= table_log_handler;
1195 slow_log_handler_list[2]= 0;
1200 void LOGGER::init_general_log(uint general_log_printer)
1202 if (general_log_printer & LOG_NONE)
1204 general_log_handler_list[0]= 0;
1208 switch (general_log_printer) {
1210 general_log_handler_list[0]= file_log_handler;
1211 general_log_handler_list[1]= 0;
1214 general_log_handler_list[0]= table_log_handler;
1215 general_log_handler_list[1]= 0;
1217 case LOG_TABLE|LOG_FILE:
1218 general_log_handler_list[0]= file_log_handler;
1219 general_log_handler_list[1]= table_log_handler;
1220 general_log_handler_list[2]= 0;
1226 bool LOGGER::activate_log_handler(THD* thd, uint log_type)
1232 case QUERY_LOG_SLOW:
1235 file_log= file_log_handler->get_mysql_slow_log();
1237 file_log->open_slow_log(opt_slow_logname);
1238 if (table_log_handler->activate_log(thd, QUERY_LOG_SLOW))
1246 init_slow_log(log_output_options);
1251 case QUERY_LOG_GENERAL:
1254 file_log= file_log_handler->get_mysql_log();
1256 file_log->open_query_log(opt_logname);
1257 if (table_log_handler->activate_log(thd, QUERY_LOG_GENERAL))
1265 init_general_log(log_output_options);
1278 void LOGGER::deactivate_log_handler(THD *thd, uint log_type)
1280 my_bool *tmp_opt= 0;
1284 case QUERY_LOG_SLOW:
1285 tmp_opt= &opt_slow_log;
1286 file_log= file_log_handler->get_mysql_slow_log();
1288 case QUERY_LOG_GENERAL:
1290 file_log= file_log_handler->get_mysql_log();
1293 MY_ASSERT_UNREACHABLE();
1307 bool Log_to_csv_event_handler::init()
1312 int LOGGER::set_handlers(uint error_log_printer,
1313 uint slow_log_printer,
1314 uint general_log_printer)
1317 DBUG_ASSERT(error_log_printer < LOG_TABLE);
1321 if ((slow_log_printer & LOG_TABLE || general_log_printer & LOG_TABLE) &&
1322 !is_log_tables_initialized)
1324 slow_log_printer= (slow_log_printer & ~LOG_TABLE) | LOG_FILE;
1325 general_log_printer= (general_log_printer & ~LOG_TABLE) | LOG_FILE;
1327 sql_print_error(
"Failed to initialize log tables. "
1328 "Falling back to the old-fashioned logs");
1331 init_error_log(error_log_printer);
1332 init_slow_log(slow_log_printer);
1333 init_general_log(general_log_printer);
1341 static int eventSource = 0;
1343 static void setup_windows_event_source()
1347 TCHAR szPath[MAX_PATH];
1355 dwError= RegCreateKey(HKEY_LOCAL_MACHINE,
1356 "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\MySQL",
1360 GetModuleFileName(NULL, szPath, MAX_PATH);
1363 dwError = RegSetValueEx(hRegKey,
"EventMessageFile", 0, REG_EXPAND_SZ,
1364 (PBYTE) szPath, (DWORD) (strlen(szPath) + 1));
1367 dwTypes= (EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |
1368 EVENTLOG_INFORMATION_TYPE);
1369 dwError= RegSetValueEx(hRegKey,
"TypesSupported", 0, REG_DWORD,
1370 (LPBYTE) &dwTypes,
sizeof dwTypes);
1372 RegCloseKey(hRegKey);
1391 static int find_uniq_filename(
char *
name)
1394 char buff[FN_REFLEN], ext_buf[FN_REFLEN];
1397 ulong max_found= 0, next= 0, number= 0;
1398 size_t buf_length, length;
1401 DBUG_ENTER(
"find_uniq_filename");
1403 length= dirname_part(buff, name, &buf_length);
1404 start= name + length;
1408 length= (size_t) (end - start + 1);
1410 if ((DBUG_EVALUATE_IF(
"error_unique_log_filename", 1,
1411 !(dir_info= my_dir(buff,MYF(MY_DONT_SORT))))))
1416 file_info= dir_info->dir_entry;
1417 for (i= dir_info->number_off_files ; i-- ; file_info++)
1419 if (memcmp(file_info->name, start, length) == 0 &&
1420 test_if_number(file_info->name+length, &number,0))
1422 set_if_bigger(max_found,(ulong) number);
1425 my_dirend(dir_info);
1428 if (max_found == MAX_LOG_UNIQUE_FN_EXT)
1430 sql_print_error(
"Log filename extension number exhausted: %06lu. \
1431 Please fix this by archiving old logs and \
1432 updating the index files.", max_found);
1437 next= max_found + 1;
1438 if (sprintf(ext_buf,
"%06lu", next)<0)
1450 if (((strlen(ext_buf) + (end - name)) >= FN_REFLEN))
1452 sql_print_error(
"Log filename too large: %s%s (%zu). \
1453 Please fix this by archiving old logs and updating the \
1454 index files.", name, ext_buf, (strlen(ext_buf) + (end - name)));
1459 if (sprintf(end,
"%06lu", next)<0)
1466 if ((next > (MAX_LOG_UNIQUE_FN_EXT - LOG_WARN_UNIQUE_FN_EXT_LEFT)))
1467 sql_print_warning(
"Next log extension: %lu. \
1468 Remaining log filename extensions: %lu. \
1469 Please consider archiving some logs.", next, (MAX_LOG_UNIQUE_FN_EXT - next));
1476 void MYSQL_LOG::init(enum_log_type log_type_arg,
1477 enum cache_type io_cache_type_arg)
1479 DBUG_ENTER(
"MYSQL_LOG::init");
1480 log_type= log_type_arg;
1481 io_cache_type= io_cache_type_arg;
1482 DBUG_PRINT(
"info",(
"log_type: %d", log_type));
1487 bool MYSQL_LOG::init_and_set_log_file_name(
const char *log_name,
1488 const char *new_name,
1489 enum_log_type log_type_arg,
1490 enum cache_type io_cache_type_arg)
1492 init(log_type_arg, io_cache_type_arg);
1494 if (new_name && !strmov(log_file_name, new_name))
1496 else if (!new_name && generate_new_name(log_file_name, log_name))
1524 bool MYSQL_LOG::open(
1525 #ifdef HAVE_PSI_INTERFACE
1526 PSI_file_key log_file_key,
1528 const char *log_name, enum_log_type log_type_arg,
1529 const char *new_name,
enum cache_type io_cache_type_arg)
1531 char buff[FN_REFLEN];
1534 int open_flags= O_CREAT | O_BINARY;
1535 DBUG_ENTER(
"MYSQL_LOG::open");
1536 DBUG_PRINT(
"enter", (
"log_type: %d", (
int) log_type_arg));
1540 if (!(name= my_strdup(log_name, MYF(MY_WME))))
1542 name= (
char *)log_name;
1546 if (init_and_set_log_file_name(name, new_name,
1547 log_type_arg, io_cache_type_arg))
1550 if (io_cache_type == SEQ_READ_APPEND)
1551 open_flags |= O_RDWR | O_APPEND;
1553 open_flags |= O_WRONLY | (log_type == LOG_BIN ? 0 : O_APPEND);
1557 #ifdef HAVE_PSI_INTERFACE
1559 m_log_file_key= log_file_key;
1563 log_file_name, open_flags,
1564 MYF(MY_WME | ME_WAITTANG))) < 0)
1569 if (my_errno == ESPIPE)
1575 if (init_io_cache(&log_file, file, IO_SIZE, io_cache_type, pos, 0,
1576 MYF(MY_WME | MY_NABP |
1577 ((log_type == LOG_BIN) ? MY_WAIT_IF_FULL : 0))))
1580 if (log_type == LOG_NORMAL)
1583 int len=my_snprintf(buff,
sizeof(buff),
"%s, Version: %s (%s). "
1584 #ifdef EMBEDDED_LIBRARY
1585 "embedded library\n",
1586 my_progname, server_version, MYSQL_COMPILATION_COMMENT
1588 "started with:\nTCP Port: %d, Named Pipe: %s\n",
1589 my_progname, server_version, MYSQL_COMPILATION_COMMENT,
1590 mysqld_port, mysqld_unix_port
1592 "started with:\nTcp port: %d Unix socket: %s\n",
1593 my_progname, server_version, MYSQL_COMPILATION_COMMENT,
1594 mysqld_port, mysqld_unix_port
1597 end= strnmov(buff + len,
"Time Id Command Argument\n",
1598 sizeof(buff) - len);
1599 if (my_b_write(&log_file, (uchar*) buff, (uint) (end-buff)) ||
1600 flush_io_cache(&log_file))
1604 log_state= LOG_OPENED;
1608 sql_print_error(
"Could not use %s for logging (error %d). \
1609 Turning logging off for the whole duration of the MySQL server process. \
1610 To turn it on again: fix the cause, \
1611 shutdown the MySQL server and restart it.", name, errno);
1614 end_io_cache(&log_file);
1617 log_state= LOG_CLOSED;
1621 MYSQL_LOG::MYSQL_LOG()
1622 : name(0), write_error(FALSE), inited(FALSE), log_type(LOG_UNKNOWN),
1623 log_state(LOG_CLOSED)
1624 #ifdef HAVE_PSI_INTERFACE
1625 , m_key_LOCK_log(key_LOG_LOCK_log)
1634 memset(&log_file, 0,
sizeof(log_file));
1637 void MYSQL_LOG::init_pthread_objects()
1639 DBUG_ASSERT(inited == 0);
1658 void MYSQL_LOG::close(uint exiting)
1660 DBUG_ENTER(
"MYSQL_LOG::close");
1661 DBUG_PRINT(
"enter",(
"exiting: %d", (
int) exiting));
1662 if (log_state == LOG_OPENED)
1664 end_io_cache(&log_file);
1668 char errbuf[MYSYS_STRERROR_SIZE];
1670 sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), name, errno,
1671 my_strerror(errbuf,
sizeof(errbuf), errno));
1676 char errbuf[MYSYS_STRERROR_SIZE];
1678 sql_print_error(ER_DEFAULT(ER_ERROR_ON_WRITE), name, errno,
1679 my_strerror(errbuf,
sizeof(errbuf), errno));
1683 log_state= (exiting & LOG_CLOSE_TO_BE_OPENED) ? LOG_TO_BE_OPENED : LOG_CLOSED;
1693 DBUG_ENTER(
"cleanup");
1704 int MYSQL_LOG::generate_new_name(
char *new_name,
const char *log_name)
1706 fn_format(new_name, log_name, mysql_data_home,
"", 4);
1707 if (log_type == LOG_BIN)
1709 if (!fn_ext(log_name)[0])
1711 if (find_uniq_filename(new_name))
1713 my_printf_error(ER_NO_UNIQUE_LOGFILE, ER(ER_NO_UNIQUE_LOGFILE),
1714 MYF(ME_FATALERROR), log_name);
1715 sql_print_error(ER(ER_NO_UNIQUE_LOGFILE), log_name);
1736 void MYSQL_QUERY_LOG::reopen_file()
1740 DBUG_ENTER(
"MYSQL_LOG::reopen_file");
1743 DBUG_PRINT(
"info",(
"log is closed"));
1751 close(LOG_CLOSE_TO_BE_OPENED);
1758 #ifdef HAVE_PSI_INTERFACE
1761 save_name, log_type, 0, io_cache_type);
1795 bool MYSQL_QUERY_LOG::write(time_t event_time,
const char *user_host,
1796 uint user_host_len, my_thread_id thread_id,
1797 const char *command_type, uint command_type_len,
1798 const char *sql_text, uint sql_text_len)
1802 char local_time_buff[MAX_TIME_SIZE];
1804 uint time_buff_len= 0;
1812 DBUG_EXECUTE_IF(
"reset_log_last_time", last_time= 0;);
1815 if (event_time != last_time)
1817 last_time= event_time;
1819 localtime_r(&event_time, &start);
1821 time_buff_len= my_snprintf(local_time_buff, MAX_TIME_SIZE,
1822 "%02d%02d%02d %2d:%02d:%02d\t",
1823 start.tm_year % 100, start.tm_mon + 1,
1824 start.tm_mday, start.tm_hour,
1825 start.tm_min, start.tm_sec);
1827 if (my_b_write(&log_file, (uchar*) local_time_buff, time_buff_len))
1831 if (my_b_write(&log_file, (uchar*)
"\t\t" ,2) < 0)
1834 length= my_snprintf(buff, 32,
"%5lu ", thread_id);
1836 if (my_b_write(&log_file, (uchar*) buff, length))
1839 if (my_b_write(&log_file, (uchar*) command_type, command_type_len))
1842 if (my_b_write(&log_file, (uchar*)
"\t", 1))
1846 if (my_b_write(&log_file, (uchar*) sql_text, sql_text_len))
1849 if (my_b_write(&log_file, (uchar*)
"\n", 1) ||
1850 flush_io_cache(&log_file))
1860 char errbuf[MYSYS_STRERROR_SIZE];
1862 sql_print_error(ER(ER_ERROR_ON_WRITE), name, errno,
1863 my_strerror(errbuf,
sizeof(errbuf), errno));
1899 bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time,
1900 time_t query_start_arg,
const char *user_host,
1901 uint user_host_len, ulonglong query_utime,
1902 ulonglong lock_utime,
bool is_command,
1903 const char *sql_text, uint sql_text_len)
1906 DBUG_ENTER(
"MYSQL_QUERY_LOG::write");
1919 char buff[80], *end;
1920 char query_time_buff[22+7], lock_time_buff[22+7];
1924 if (!(specialflag & SPECIAL_SHORT_LOG_FORMAT))
1926 if (current_time != last_time)
1928 last_time= current_time;
1930 localtime_r(¤t_time, &start);
1932 buff_len= my_snprintf(buff,
sizeof buff,
1933 "# Time: %02d%02d%02d %2d:%02d:%02d\n",
1934 start.tm_year % 100, start.tm_mon + 1,
1935 start.tm_mday, start.tm_hour,
1936 start.tm_min, start.tm_sec);
1939 if (my_b_write(&log_file, (uchar*) buff, buff_len))
1942 buff_len= my_snprintf(buff, 32,
"%5lu", thd->thread_id);
1943 if (my_b_printf(&log_file,
"# User@Host: %s Id: %s\n", user_host, buff)
1948 sprintf(query_time_buff,
"%.6f", ulonglong2double(query_utime)/1000000.0);
1949 sprintf(lock_time_buff,
"%.6f", ulonglong2double(lock_utime)/1000000.0);
1950 if (my_b_printf(&log_file,
1951 "# Query_time: %s Lock_time: %s"
1952 " Rows_sent: %lu Rows_examined: %lu\n",
1953 query_time_buff, lock_time_buff,
1954 (ulong) thd->get_sent_row_count(),
1955 (ulong) thd->get_examined_row_count()) == (uint) -1)
1957 if (thd->db && strcmp(thd->db, db))
1959 if (my_b_printf(&log_file,
"use %s;\n",thd->db) == (uint) -1)
1963 if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt)
1965 end=strmov(end,
",last_insert_id=");
1966 end=longlong10_to_str((longlong)
1967 thd->first_successful_insert_id_in_prev_stmt_for_binlog,
1971 if (thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements() > 0)
1973 if (!(specialflag & SPECIAL_SHORT_LOG_FORMAT))
1975 end=strmov(end,
",insert_id=");
1976 end=longlong10_to_str((longlong)
1977 thd->auto_inc_intervals_in_cur_stmt_for_binlog.minimum(),
1987 end= strmov(end,
",timestamp=");
1988 end= int10_to_str((
long) current_time, end, 10);
1994 if (my_b_write(&log_file, (uchar*)
"SET ", 4) ||
1995 my_b_write(&log_file, (uchar*) buff + 1, (uint) (end-buff)))
2000 end= strxmov(buff,
"# administrator command: ", NullS);
2001 buff_len= (ulong) (end - buff);
2002 DBUG_EXECUTE_IF(
"simulate_slow_log_write_error",
2003 {DBUG_SET(
"+d,simulate_file_write_error");});
2004 if(my_b_write(&log_file, (uchar*) buff, buff_len))
2007 if (my_b_write(&log_file, (uchar*) sql_text, sql_text_len) ||
2008 my_b_write(&log_file, (uchar*)
";\n",2) ||
2009 flush_io_cache(&log_file))
2016 char errbuf[MYSYS_STRERROR_SIZE];
2018 sql_print_error(ER(ER_ERROR_ON_WRITE), name, error,
2019 my_strerror(errbuf,
sizeof(errbuf), errno));
2035 bool strip_ext,
char *buff)
2037 if (!log_name || !log_name[0])
2039 strmake(buff, pidfile_name, FN_REFLEN - strlen(suffix) - 1);
2040 return (
const char *)
2041 fn_format(buff, buff,
"", suffix, MYF(MY_REPLACE_EXT|MY_REPLACE_DIR));
2046 char *p= fn_ext(log_name);
2047 uint length= (uint) (p - log_name);
2048 strmake(buff, log_name, min<size_t>(length, FN_REFLEN-1));
2049 return (
const char*)buff;
2055 int error_log_print(
enum loglevel level,
const char *format,
2058 return logger.error_log_print(level, format, args);
2062 bool slow_log_print(THD *thd,
const char *query, uint query_length)
2064 return logger.slow_log_print(thd, query, query_length);
2068 bool LOGGER::log_command(THD *thd,
enum enum_server_command command)
2070 #ifndef NO_EMBEDDED_ACCESS_CHECKS
2071 Security_context *sctx= thd->security_ctx;
2077 if (*general_log_handler_list && (what_to_log & (1L << (uint) command)))
2079 if ((thd->variables.option_bits & OPTION_LOG_OFF)
2080 #ifndef NO_EMBEDDED_ACCESS_CHECKS
2081 && (sctx->master_access & SUPER_ACL)
2096 bool general_log_print(THD *thd,
enum enum_server_command command,
2097 const char *format, ...)
2103 if (! logger.log_command(thd, command))
2106 va_start(args, format);
2107 error= logger.general_log_print(thd, command, format, args);
2113 bool general_log_write(THD *thd,
enum enum_server_command command,
2114 const char *query, uint query_length)
2117 if (logger.log_command(thd, command))
2118 return logger.general_log_write(thd, command, query, query_length);
2140 static bool test_if_number(
register const char *str,
2141 ulong *res,
bool allow_wildcards)
2145 DBUG_ENTER(
"test_if_number");
2148 while (*str++ ==
' ') ;
2149 if (*--str ==
'-' || *str ==
'+')
2151 while (my_isdigit(files_charset_info,*str) ||
2152 (allow_wildcards && (*str == wild_many || *str == wild_one)))
2160 my_isdigit(files_charset_info,*str) ||
2161 (allow_wildcards && (*str == wild_many || *str == wild_one)) ;
2164 if (*str != 0 || flag == 0)
2172 void sql_perror(
const char *
message)
2174 #ifdef HAVE_STRERROR
2175 sql_print_error(
"%s: %s",message, strerror(errno));
2187 extern "C" my_bool reopen_fstreams(
const char *filename,
2188 FILE *outstream, FILE *errstream)
2190 if (outstream && !my_freopen(filename,
"a", outstream))
2193 if (errstream && !my_freopen(filename,
"a", errstream))
2198 setbuf(errstream, NULL);
2208 static bool redirect_std_streams(
const char *file)
2210 if (reopen_fstreams(file, stdout, stderr))
2213 setbuf(stderr, NULL);
2218 bool flush_error_log()
2224 if (redirect_std_streams(log_error_file))
2232 static void print_buffer_to_nt_eventlog(
enum loglevel level,
char *buff,
2233 size_t length,
size_t buffLen)
2236 char *buffptr= buff;
2237 DBUG_ENTER(
"print_buffer_to_nt_eventlog");
2240 strmov(buffptr+min(length, buffLen-5),
"\r\n\r\n");
2242 setup_windows_event_source();
2243 if ((event= RegisterEventSource(NULL,
"MySQL")))
2247 ReportEvent(event, EVENTLOG_ERROR_TYPE, 0, MSG_DEFAULT, NULL, 1, 0,
2248 (LPCSTR*)&buffptr, NULL);
2251 ReportEvent(event, EVENTLOG_WARNING_TYPE, 0, MSG_DEFAULT, NULL, 1, 0,
2252 (LPCSTR*) &buffptr, NULL);
2254 case INFORMATION_LEVEL:
2255 ReportEvent(event, EVENTLOG_INFORMATION_TYPE, 0, MSG_DEFAULT, NULL, 1,
2256 0, (LPCSTR*) &buffptr, NULL);
2259 DeregisterEventSource(event);
2267 #ifndef EMBEDDED_LIBRARY
2268 static void print_buffer_to_file(
enum loglevel level,
const char *buffer,
2274 DBUG_ENTER(
"print_buffer_to_file");
2275 DBUG_PRINT(
"enter",(
"buffer: %s", buffer));
2280 localtime_r(&skr, &tm_tmp);
2283 fprintf(stderr,
"%d-%02d-%02d %02d:%02d:%02d %lu [%s] %.*s\n",
2284 start->tm_year + 1900,
2291 (level == ERROR_LEVEL ?
"ERROR" : level == WARNING_LEVEL ?
2292 "Warning" :
"Note"),
2293 (
int) length, buffer);
2321 DBUG_ENTER(
"vprint_msg_to_log");
2323 length= my_vsnprintf(buff,
sizeof(buff), format, args);
2324 print_buffer_to_file(level, buff, length);
2327 print_buffer_to_nt_eventlog(level, buff, length,
sizeof(buff));
2335 void sql_print_error(
const char *format, ...)
2338 DBUG_ENTER(
"sql_print_error");
2340 va_start(args, format);
2341 error_log_print(ERROR_LEVEL, format, args);
2348 void sql_print_warning(
const char *format, ...)
2351 DBUG_ENTER(
"sql_print_warning");
2353 va_start(args, format);
2354 error_log_print(WARNING_LEVEL, format, args);
2361 void sql_print_information(
const char *format, ...)
2364 DBUG_ENTER(
"sql_print_information");
2366 va_start(args, format);
2367 error_log_print(INFORMATION_LEVEL, format, args);
2375 int my_plugin_log_message(MYSQL_PLUGIN *plugin_ptr, plugin_log_level level,
2376 const char *format, ...)
2378 char format2[MYSQL_ERRMSG_SIZE];
2384 DBUG_ASSERT(level >= MY_ERROR_LEVEL || level <= MY_INFORMATION_LEVEL);
2388 case MY_ERROR_LEVEL: lvl= ERROR_LEVEL;
break;
2389 case MY_WARNING_LEVEL: lvl= WARNING_LEVEL;
break;
2390 case MY_INFORMATION_LEVEL: lvl= INFORMATION_LEVEL;
break;
2394 va_start(args, format);
2395 snprintf(format2,
sizeof (format2) - 1,
"Plugin %.*s reported: '%s'",
2396 (
int) plugin->name.length, plugin->name.str, format);
2397 ret= error_log_print(lvl, format2, args);
2441 ulong tc_log_page_waits= 0;
2445 #define TC_LOG_HEADER_SIZE (sizeof(tc_log_magic)+1)
2447 static const char tc_log_magic[]={(char) 254, 0x23, 0x05, 0x74};
2449 ulong opt_tc_log_size= TC_LOG_MIN_SIZE;
2450 ulong tc_log_max_pages_used=0, tc_log_page_size=0, tc_log_cur_pages_used=0;
2452 int TC_LOG_MMAP::open(
const char *opt_name)
2458 DBUG_ASSERT(total_ha_2pc > 1);
2459 DBUG_ASSERT(opt_name && opt_name[0]);
2461 tc_log_page_size= my_getpagesize();
2462 if (TC_LOG_PAGE_SIZE > tc_log_page_size)
2464 DBUG_ASSERT(TC_LOG_PAGE_SIZE % tc_log_page_size == 0);
2467 fn_format(logname,opt_name,mysql_data_home,
"",MY_UNPACK_FILENAME);
2468 if ((fd=
mysql_file_open(key_file_tclog, logname, O_RDWR, MYF(0))) < 0)
2470 if (my_errno != ENOENT)
2472 if (using_heuristic_recover())
2475 O_RDWR, MYF(MY_WME))) < 0)
2478 file_length= opt_tc_log_size;
2486 sql_print_information(
"Recovering after a crash using %s", opt_name);
2487 if (tc_heuristic_recover)
2489 sql_print_error(
"Cannot perform automatic crash recovery when "
2490 "--tc-heuristic-recover is used");
2493 file_length=
mysql_file_seek(fd, 0L, MY_SEEK_END, MYF(MY_WME+MY_FAE));
2494 if (file_length == MY_FILEPOS_ERROR || file_length % tc_log_page_size)
2498 data= (uchar *)my_mmap(0, (
size_t)file_length, PROT_READ|PROT_WRITE,
2499 MAP_NOSYNC|MAP_SHARED, fd, 0);
2500 if (data == MAP_FAILED)
2507 npages=(uint)file_length/tc_log_page_size;
2508 DBUG_ASSERT(npages >= 3);
2509 if (!(pages=(PAGE *)my_malloc(npages*
sizeof(PAGE), MYF(MY_WME|MY_ZEROFILL))))
2512 for (pg=pages, i=0; i < npages; i++, pg++)
2519 pg->start=(my_xid *)(data + i*tc_log_page_size);
2520 pg->end=(my_xid *)(pg->start + tc_log_page_size);
2521 pg->size=pg->free=tc_log_page_size/
sizeof(my_xid);
2523 pages[0].size=pages[0].free=
2524 (tc_log_page_size-TC_LOG_HEADER_SIZE)/
sizeof(my_xid);
2525 pages[0].start=pages[0].end-pages[0].size;
2526 pages[npages-1].next=0;
2529 if (crashed && recover())
2532 memcpy(data, tc_log_magic,
sizeof(tc_log_magic));
2533 data[
sizeof(tc_log_magic)]= (uchar)total_ha_2pc;
2534 my_msync(fd, data, tc_log_page_size, MS_SYNC);
2548 pool_last=pages+npages-1;
2569 void TC_LOG_MMAP::get_active_from_pool()
2571 PAGE **p, **best_p=0;
2580 if ((*p)->waiters == 0)
2584 for (p=&(*p)->next; *p; p=&(*p)->next)
2586 if ((*p)->waiters == 0 && (*p)->free > best_free)
2588 best_free=(*p)->free;
2593 while ((*best_p == 0 || best_free == 0) && overflow());
2596 if (active->free == active->size)
2598 tc_log_cur_pages_used++;
2599 set_if_bigger(tc_log_max_pages_used, tc_log_cur_pages_used);
2602 if ((*best_p)->next)
2603 *best_p=(*best_p)->next;
2615 int TC_LOG_MMAP::overflow()
2622 tc_log_page_waits++;
2634 TC_LOG::enum_result TC_LOG_MMAP::commit(THD *thd,
bool all)
2636 DBUG_ENTER(
"TC_LOG_MMAP::commit");
2637 unsigned long cookie= 0;
2638 my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
2641 if ((cookie= log_xid(thd, xid)))
2642 DBUG_RETURN(RESULT_ABORTED);
2645 DBUG_RETURN(RESULT_INCONSISTENT);
2649 if (unlog(cookie, xid))
2650 DBUG_RETURN(RESULT_INCONSISTENT);
2651 DBUG_RETURN(RESULT_SUCCESS);
2682 int TC_LOG_MMAP::log_xid(THD *thd, my_xid xid)
2697 while (unlikely(active && active->free == 0))
2702 get_active_from_pool();
2711 DBUG_ASSERT(p->ptr < p->end);
2715 cookie= (ulong)((uchar *)p->ptr - data);
2732 while (p->state == PS_DIRTY && syncing)
2735 err= p->state == PS_ERROR;
2736 if (p->state != PS_DIRTY)
2738 if (p->waiters == 0)
2744 DBUG_ASSERT(active == p && syncing == 0);
2754 return err ? 0 : cookie;
2757 int TC_LOG_MMAP::sync()
2761 DBUG_ASSERT(syncing != active);
2767 err= my_msync(fd, syncing->start, 1, MS_SYNC);
2771 pool_last->next=syncing;
2774 syncing->state= err ? PS_ERROR : PS_POOL;
2792 int TC_LOG_MMAP::unlog(ulong cookie, my_xid xid)
2794 PAGE *p=pages+(cookie/tc_log_page_size);
2795 my_xid *x=(my_xid *)(data+cookie);
2797 DBUG_ASSERT(*x == xid);
2798 DBUG_ASSERT(x >= p->start && x < p->end);
2803 DBUG_ASSERT(p->free <= p->size);
2804 set_if_smaller(p->ptr, x);
2805 if (p->free == p->size)
2806 statistic_decrement(tc_log_cur_pages_used, &LOCK_status);
2807 if (p->waiters == 0)
2813 void TC_LOG_MMAP::close()
2825 for (i=0; i < npages; i++)
2827 if (pages[i].ptr == 0)
2835 my_munmap((
char*)data, (
size_t)file_length);
2844 int TC_LOG_MMAP::recover()
2847 PAGE *p=pages, *end_p=pages+npages;
2849 if (memcmp(data, tc_log_magic,
sizeof(tc_log_magic)))
2851 sql_print_error(
"Bad magic header in tc log");
2859 if (data[
sizeof(tc_log_magic)] != total_ha_2pc)
2861 sql_print_error(
"Recovery failed! You must enable "
2862 "exactly %d storage engines that support "
2863 "two-phase commit protocol",
2864 data[
sizeof(tc_log_magic)]);
2868 if (my_hash_init(&xids, &my_charset_bin, tc_log_page_size/3, 0,
2869 sizeof(my_xid), 0, 0, MYF(0)))
2872 for ( ; p < end_p ; p++)
2874 for (my_xid *x=p->start; x < p->end; x++)
2875 if (*x && my_hash_insert(&xids, (uchar *)x))
2879 if (ha_recover(&xids))
2882 my_hash_free(&xids);
2883 memset(data, 0, (
size_t)file_length);
2887 my_hash_free(&xids);
2889 sql_print_error(
"Crash recovery failed. Either correct the problem "
2890 "(if it's, for example, out of memory error) and restart, "
2891 "or delete tc log and start mysqld with "
2892 "--tc-heuristic-recover={commit|rollback}");
2899 TC_LOG_MMAP tc_log_mmap;
2916 if (!tc_heuristic_recover)
2919 sql_print_information(
"Heuristic crash recovery mode");
2921 sql_print_error(
"Heuristic crash recovery failed");
2922 sql_print_information(
"Please restart mysqld without --tc-heuristic-recover");