1 /* Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License, version 2.0, 5 as published by the Free Software Foundation. 6 7 This program is also distributed with certain software (including 8 but not limited to OpenSSL) that is licensed under separate terms, 9 as designated in a particular file or component or in included license 10 documentation. The authors of MySQL hereby grant you an additional 11 permission to link the program and your derivative works with the 12 separately licensed software that they have included with MySQL. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License, version 2.0, for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 22 23 #ifndef LOG_H 24 #define LOG_H 25 26 #include "unireg.h" // REQUIRED: for other includes 27 #include "handler.h" /* my_xid */ 28 29 /** 30 the struct aggregates two paramenters that identify an event 31 uniquely in scope of communication of a particular master and slave couple. 32 I.e there can not be 2 events from the same staying connected master which 33 have the same coordinates. 34 @note 35 Such identifier is not yet unique generally as the event originating master 36 is resetable. Also the crashed master can be replaced with some other. 37 */ 38 typedef struct event_coordinates 39 { 40 char * file_name; // binlog file name (directories stripped) 41 my_off_t pos; // event's position in the binlog file 42 } LOG_POS_COORD; 43 44 /** 45 Transaction Coordinator Log. 46 47 A base abstract class for three different implementations of the 48 transaction coordinator. 49 50 The server uses the transaction coordinator to order transactions 51 correctly and there are three different implementations: one using 52 an in-memory structure, one dummy that does not do anything, and one 53 using the binary log for transaction coordination. 54 */ 55 class TC_LOG 56 { 57 public: 58 int using_heuristic_recover(); TC_LOG()59 TC_LOG() {} ~TC_LOG()60 virtual ~TC_LOG() {} 61 62 enum enum_result { 63 RESULT_SUCCESS, 64 RESULT_ABORTED, 65 RESULT_INCONSISTENT 66 }; 67 68 virtual int open(const char *opt_name)=0; 69 virtual void close()=0; 70 71 /** 72 Log a commit record of the transaction to the transaction 73 coordinator log. 74 75 When the function returns, the transaction commit is properly 76 logged to the transaction coordinator log and can be committed in 77 the storage engines. 78 79 @param thd Session to log transaction for. 80 @param all @c True if this is a "real" commit, @c false if it is a "statement" commit. 81 82 @return Error code on failure, zero on success. 83 */ 84 virtual enum_result commit(THD *thd, bool all) = 0; 85 86 /** 87 Log a rollback record of the transaction to the transaction 88 coordinator log. 89 90 When the function returns, the transaction have been aborted in 91 the transaction coordinator log. 92 93 @param thd Session to log transaction record for. 94 95 @param all @c true if an explicit commit or an implicit commit 96 for a statement, @c false if an internal commit of the statement. 97 98 @return Error code on failure, zero on success. 99 */ 100 virtual int rollback(THD *thd, bool all) = 0; 101 /** 102 Log a prepare record of the transaction to the storage engines. 103 104 @param thd Session to log transaction record for. 105 106 @param all @c true if an explicit commit or an implicit commit 107 for a statement, @c false if an internal commit of the statement. 108 109 @return Error code on failure, zero on success. 110 */ 111 virtual int prepare(THD *thd, bool all) = 0; 112 }; 113 114 115 class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging 116 { 117 public: TC_LOG_DUMMY()118 TC_LOG_DUMMY() {} open(const char * opt_name)119 int open(const char *opt_name) { return 0; } close()120 void close() { } commit(THD * thd,bool all)121 enum_result commit(THD *thd, bool all) { 122 return ha_commit_low(thd, all) ? RESULT_ABORTED : RESULT_SUCCESS; 123 } rollback(THD * thd,bool all)124 int rollback(THD *thd, bool all) { 125 return ha_rollback_low(thd, all); 126 } prepare(THD * thd,bool all)127 int prepare(THD *thd, bool all) { 128 return ha_prepare_low(thd, all); 129 } 130 }; 131 132 #ifdef HAVE_MMAP 133 class TC_LOG_MMAP: public TC_LOG 134 { 135 public: // only to keep Sun Forte on sol9x86 happy 136 typedef enum { 137 PS_POOL, // page is in pool 138 PS_ERROR, // last sync failed 139 PS_DIRTY // new xids added since last sync 140 } PAGE_STATE; 141 142 private: 143 typedef struct st_page { 144 struct st_page *next; // page a linked in a fifo queue 145 my_xid *start, *end; // usable area of a page 146 my_xid *ptr; // next xid will be written here 147 int size, free; // max and current number of free xid slots on the page 148 int waiters; // number of waiters on condition 149 PAGE_STATE state; // see above 150 mysql_mutex_t lock; // to access page data or control structure 151 mysql_cond_t cond; // to wait for a sync 152 } PAGE; 153 154 char logname[FN_REFLEN]; 155 File fd; 156 my_off_t file_length; 157 uint npages, inited; 158 uchar *data; 159 struct st_page *pages, *syncing, *active, *pool, *pool_last; 160 /* 161 note that, e.g. LOCK_active is only used to protect 162 'active' pointer, to protect the content of the active page 163 one has to use active->lock. 164 Same for LOCK_pool and LOCK_sync 165 */ 166 mysql_mutex_t LOCK_active, LOCK_pool, LOCK_sync; 167 mysql_cond_t COND_pool, COND_active; 168 169 public: TC_LOG_MMAP()170 TC_LOG_MMAP(): inited(0) {} 171 int open(const char *opt_name); 172 void close(); 173 enum_result commit(THD *thd, bool all); rollback(THD * thd,bool all)174 int rollback(THD *thd, bool all) { return ha_rollback_low(thd, all); } prepare(THD * thd,bool all)175 int prepare(THD *thd, bool all) { return ha_prepare_low(thd, all); } 176 int recover(); 177 178 private: 179 int log_xid(THD *thd, my_xid xid); 180 int unlog(ulong cookie, my_xid xid); 181 void get_active_from_pool(); 182 int sync(); 183 int overflow(); 184 }; 185 #else 186 #define TC_LOG_MMAP TC_LOG_DUMMY 187 #endif 188 189 extern TC_LOG *tc_log; 190 extern TC_LOG_MMAP tc_log_mmap; 191 extern TC_LOG_DUMMY tc_log_dummy; 192 193 /* log info errors */ 194 #define LOG_INFO_EOF -1 195 #define LOG_INFO_IO -2 196 #define LOG_INFO_INVALID -3 197 #define LOG_INFO_SEEK -4 198 #define LOG_INFO_MEM -6 199 #define LOG_INFO_FATAL -7 200 #define LOG_INFO_IN_USE -8 201 #define LOG_INFO_EMFILE -9 202 203 204 /* bitmap to SQL_LOG::close() */ 205 #define LOG_CLOSE_INDEX 1 206 #define LOG_CLOSE_TO_BE_OPENED 2 207 #define LOG_CLOSE_STOP_EVENT 4 208 209 /* 210 Maximum unique log filename extension. 211 Note: setting to 0x7FFFFFFF due to atol windows 212 overflow/truncate. 213 */ 214 #define MAX_LOG_UNIQUE_FN_EXT 0x7FFFFFFF 215 216 /* 217 Number of warnings that will be printed to error log 218 before extension number is exhausted. 219 */ 220 #define LOG_WARN_UNIQUE_FN_EXT_LEFT 1000 221 222 /* max size of log messages (error log, plugins' logging, general log) */ 223 #define MAX_LOG_BUFFER_SIZE 1024 224 #define MAX_TIME_SIZE 32 225 226 #ifdef HAVE_PSI_INTERFACE 227 extern PSI_mutex_key key_LOG_INFO_lock; 228 #endif 229 230 /* 231 Note that we destroy the lock mutex in the desctructor here. 232 This means that object instances cannot be destroyed/go out of scope, 233 until we have reset thd->current_linfo to NULL; 234 */ 235 typedef struct st_log_info 236 { 237 char log_file_name[FN_REFLEN]; 238 my_off_t index_file_offset, index_file_start_offset; 239 my_off_t pos; 240 bool fatal; // if the purge happens to give us a negative offset 241 int entry_index; //used in purge_logs(), calculatd in find_log_pos(). 242 mysql_mutex_t lock; st_log_infost_log_info243 st_log_info() 244 : index_file_offset(0), index_file_start_offset(0), 245 pos(0), fatal(0), entry_index(0) 246 { 247 log_file_name[0] = '\0'; 248 mysql_mutex_init(key_LOG_INFO_lock, &lock, MY_MUTEX_INIT_FAST); 249 } ~st_log_infost_log_info250 ~st_log_info() { mysql_mutex_destroy(&lock);} 251 } LOG_INFO; 252 253 /* 254 Currently we have only 3 kinds of logging functions: old-fashioned 255 logs, stdout and csv logging routines. 256 */ 257 #define MAX_LOG_HANDLERS_NUM 3 258 259 /* log event handler flags */ 260 #define LOG_NONE 1 261 #define LOG_FILE 2 262 #define LOG_TABLE 4 263 264 enum enum_log_type { LOG_UNKNOWN, LOG_NORMAL, LOG_BIN }; 265 enum enum_log_state { LOG_OPENED, LOG_CLOSED, LOG_TO_BE_OPENED }; 266 267 /* 268 TODO use mmap instead of IO_CACHE for binlog 269 (mmap+fsync is two times faster than write+fsync) 270 */ 271 272 class MYSQL_LOG 273 { 274 public: 275 MYSQL_LOG(); 276 void init_pthread_objects(); 277 void cleanup(); 278 bool open( 279 #ifdef HAVE_PSI_INTERFACE 280 PSI_file_key log_file_key, 281 #endif 282 const char *log_name, 283 enum_log_type log_type, 284 const char *new_name, 285 enum cache_type io_cache_type_arg); 286 bool init_and_set_log_file_name(const char *log_name, 287 const char *new_name, 288 enum_log_type log_type_arg, 289 enum cache_type io_cache_type_arg); 290 void init(enum_log_type log_type_arg, 291 enum cache_type io_cache_type_arg); 292 void close(uint exiting); is_open()293 inline bool is_open() { return log_state != LOG_CLOSED; } 294 const char *generate_name(const char *log_name, const char *suffix, 295 bool strip_ext, char *buff); 296 int generate_new_name(char *new_name, const char *log_name); 297 protected: 298 /* LOCK_log is inited by init_pthread_objects() */ 299 mysql_mutex_t LOCK_log; 300 char *name; 301 char log_file_name[FN_REFLEN]; 302 char time_buff[20], db[NAME_LEN + 1]; 303 bool write_error, inited; 304 IO_CACHE log_file; 305 enum_log_type log_type; 306 volatile enum_log_state log_state; 307 enum cache_type io_cache_type; 308 friend class Log_event; 309 #ifdef HAVE_PSI_INTERFACE 310 /** Instrumentation key to use for file io in @c log_file */ 311 PSI_file_key m_log_file_key; 312 /** The instrumentation key to use for @ LOCK_log. */ 313 PSI_mutex_key m_key_LOCK_log; 314 #endif 315 }; 316 317 318 enum enum_general_log_table_field 319 { 320 GLT_FIELD_EVENT_TIME = 0, 321 GLT_FIELD_USER_HOST, 322 GLT_FIELD_THREAD_ID, 323 GLT_FIELD_SERVER_ID, 324 GLT_FIELD_COMMAND_TYPE, 325 GLT_FIELD_ARGUMENT, 326 GLT_FIELD_COUNT 327 }; 328 329 330 enum enum_slow_query_log_table_field 331 { 332 SQLT_FIELD_START_TIME = 0, 333 SQLT_FIELD_USER_HOST, 334 SQLT_FIELD_QUERY_TIME, 335 SQLT_FIELD_LOCK_TIME, 336 SQLT_FIELD_ROWS_SENT, 337 SQLT_FIELD_ROWS_EXAMINED, 338 SQLT_FIELD_DATABASE, 339 SQLT_FIELD_LAST_INSERT_ID, 340 SQLT_FIELD_INSERT_ID, 341 SQLT_FIELD_SERVER_ID, 342 SQLT_FIELD_SQL_TEXT, 343 SQLT_FIELD_THREAD_ID, 344 SQLT_FIELD_COUNT 345 }; 346 347 348 class MYSQL_QUERY_LOG: public MYSQL_LOG 349 { 350 public: MYSQL_QUERY_LOG()351 MYSQL_QUERY_LOG() : last_time(0) {} 352 bool reopen_file(); 353 bool write(time_t event_time, const char *user_host, 354 uint user_host_len, my_thread_id thread_id, 355 const char *command_type, uint command_type_len, 356 const char *sql_text, uint sql_text_len); 357 bool write(THD *thd, time_t current_time, time_t query_start_arg, 358 const char *user_host, uint user_host_len, 359 ulonglong query_utime, ulonglong lock_utime, bool is_command, 360 const char *sql_text, uint sql_text_len); open_slow_log(const char * log_name)361 bool open_slow_log(const char *log_name) 362 { 363 char buf[FN_REFLEN]; 364 return open( 365 #ifdef HAVE_PSI_INTERFACE 366 key_file_slow_log, 367 #endif 368 generate_name(log_name, "-slow.log", 0, buf), 369 LOG_NORMAL, 0, WRITE_CACHE); 370 } open_query_log(const char * log_name)371 bool open_query_log(const char *log_name) 372 { 373 char buf[FN_REFLEN]; 374 return open( 375 #ifdef HAVE_PSI_INTERFACE 376 key_file_query_log, 377 #endif 378 generate_name(log_name, ".log", 0, buf), 379 LOG_NORMAL, 0, WRITE_CACHE); 380 } 381 382 private: 383 time_t last_time; 384 }; 385 386 class Log_event_handler 387 { 388 public: Log_event_handler()389 Log_event_handler() {} 390 virtual bool init()= 0; 391 virtual void cleanup()= 0; 392 393 virtual bool log_slow(THD *thd, time_t current_time, 394 time_t query_start_arg, const char *user_host, 395 uint user_host_len, ulonglong query_utime, 396 ulonglong lock_utime, bool is_command, 397 const char *sql_text, uint sql_text_len)= 0; 398 virtual bool log_error(enum loglevel level, const char *format, 399 va_list args)= 0; 400 virtual bool log_general(THD *thd, time_t event_time, const char *user_host, 401 uint user_host_len, my_thread_id thread_id, 402 const char *command_type, uint command_type_len, 403 const char *sql_text, uint sql_text_len, 404 const CHARSET_INFO *client_cs)= 0; ~Log_event_handler()405 virtual ~Log_event_handler() {} 406 }; 407 408 409 int check_if_log_table(size_t db_len, const char *db, size_t table_name_len, 410 const char *table_name, bool check_if_opened); 411 412 class Log_to_csv_event_handler: public Log_event_handler 413 { 414 public: 415 Log_to_csv_event_handler(); 416 ~Log_to_csv_event_handler(); 417 virtual bool init(); 418 virtual void cleanup(); 419 420 virtual bool log_slow(THD *thd, time_t current_time, 421 time_t query_start_arg, const char *user_host, 422 uint user_host_len, ulonglong query_utime, 423 ulonglong lock_utime, bool is_command, 424 const char *sql_text, uint sql_text_len); 425 virtual bool log_error(enum loglevel level, const char *format, 426 va_list args); 427 virtual bool log_general(THD *thd, time_t event_time, const char *user_host, 428 uint user_host_len, my_thread_id thread_id, 429 const char *command_type, uint command_type_len, 430 const char *sql_text, uint sql_text_len, 431 const CHARSET_INFO *client_cs); 432 433 int activate_log(THD *thd, uint log_type); 434 }; 435 436 437 /* type of the log table */ 438 #define QUERY_LOG_SLOW 1 439 #define QUERY_LOG_GENERAL 2 440 441 class Log_to_file_event_handler: public Log_event_handler 442 { 443 MYSQL_QUERY_LOG mysql_log; 444 MYSQL_QUERY_LOG mysql_slow_log; 445 bool is_initialized; 446 public: Log_to_file_event_handler()447 Log_to_file_event_handler(): is_initialized(FALSE) 448 {} 449 virtual bool init(); 450 virtual void cleanup(); 451 452 virtual bool log_slow(THD *thd, time_t current_time, 453 time_t query_start_arg, const char *user_host, 454 uint user_host_len, ulonglong query_utime, 455 ulonglong lock_utime, bool is_command, 456 const char *sql_text, uint sql_text_len); 457 virtual bool log_error(enum loglevel level, const char *format, 458 va_list args); 459 virtual bool log_general(THD *thd, time_t event_time, const char *user_host, 460 uint user_host_len, my_thread_id thread_id, 461 const char *command_type, uint command_type_len, 462 const char *sql_text, uint sql_text_len, 463 const CHARSET_INFO *client_cs); 464 void flush(); 465 void init_pthread_objects(); get_mysql_slow_log()466 MYSQL_QUERY_LOG *get_mysql_slow_log() { return &mysql_slow_log; } get_mysql_log()467 MYSQL_QUERY_LOG *get_mysql_log() { return &mysql_log; } 468 }; 469 470 471 /* Class which manages slow, general and error log event handlers */ 472 class LOGGER 473 { 474 mysql_rwlock_t LOCK_logger; 475 /* flag to check whether logger mutex is initialized */ 476 uint inited; 477 478 /* available log handlers */ 479 Log_to_csv_event_handler *table_log_handler; 480 Log_to_file_event_handler *file_log_handler; 481 482 /* NULL-terminated arrays of log handlers */ 483 Log_event_handler *error_log_handler_list[MAX_LOG_HANDLERS_NUM + 1]; 484 Log_event_handler *slow_log_handler_list[MAX_LOG_HANDLERS_NUM + 1]; 485 Log_event_handler *general_log_handler_list[MAX_LOG_HANDLERS_NUM + 1]; 486 487 public: 488 489 bool is_log_tables_initialized; 490 LOGGER()491 LOGGER() : inited(0), table_log_handler(NULL), 492 file_log_handler(NULL), is_log_tables_initialized(FALSE) 493 {} lock_shared()494 void lock_shared() { mysql_rwlock_rdlock(&LOCK_logger); } lock_exclusive()495 void lock_exclusive() { mysql_rwlock_wrlock(&LOCK_logger); } unlock()496 void unlock() { mysql_rwlock_unlock(&LOCK_logger); } 497 bool is_log_table_enabled(uint log_table_type); 498 bool log_command(THD *thd, enum enum_server_command command, 499 const char *query_str, size_t query_length); 500 501 /* 502 We want to initialize all log mutexes as soon as possible, 503 but we cannot do it in constructor, as safe_mutex relies on 504 initialization, performed by MY_INIT(). This why this is done in 505 this function. 506 */ 507 void init_base(); 508 void init_log_tables(); 509 bool flush_logs(THD *thd); 510 bool flush_slow_log(); 511 bool flush_general_log(); 512 /* Perform basic logger cleanup. this will leave e.g. error log open. */ 513 void cleanup_base(); 514 /* Free memory. Nothing could be logged after this function is called */ 515 void cleanup_end(); 516 bool error_log_print(enum loglevel level, const char *format, 517 va_list args); 518 bool slow_log_print(THD *thd, const char *query, uint query_length); 519 bool general_log_print(THD *thd,enum enum_server_command command, 520 const char *format, va_list args); 521 bool general_log_write(THD *thd, enum enum_server_command command, 522 const char *query, uint query_length); 523 524 /* we use this function to setup all enabled log event handlers */ 525 int set_handlers(uint error_log_printer, 526 uint slow_log_printer, 527 uint general_log_printer); 528 void init_error_log(uint error_log_printer); 529 void init_slow_log(uint slow_log_printer); 530 void init_general_log(uint general_log_printer); 531 void deactivate_log_handler(THD* thd, uint log_type); 532 bool activate_log_handler(THD* thd, uint log_type); get_slow_log_file_handler()533 MYSQL_QUERY_LOG *get_slow_log_file_handler() const 534 { 535 if (file_log_handler) 536 return file_log_handler->get_mysql_slow_log(); 537 return NULL; 538 } get_log_file_handler()539 MYSQL_QUERY_LOG *get_log_file_handler() const 540 { 541 if (file_log_handler) 542 return file_log_handler->get_mysql_log(); 543 return NULL; 544 } 545 }; 546 547 enum enum_binlog_row_image { 548 /** PKE in the before image and changed columns in the after image */ 549 BINLOG_ROW_IMAGE_MINIMAL= 0, 550 /** Whenever possible, before and after image contain all columns except blobs. */ 551 BINLOG_ROW_IMAGE_NOBLOB= 1, 552 /** All columns in both before and after image. */ 553 BINLOG_ROW_IMAGE_FULL= 2 554 }; 555 556 enum enum_binlog_format { 557 BINLOG_FORMAT_MIXED= 0, ///< statement if safe, otherwise row - autodetected 558 BINLOG_FORMAT_STMT= 1, ///< statement-based 559 BINLOG_FORMAT_ROW= 2, ///< row-based 560 BINLOG_FORMAT_UNSPEC=3 ///< thd_binlog_format() returns it when binlog is closed 561 }; 562 563 void exec_binlog_error_action_abort(const char* err_string); 564 int query_error_code(THD *thd, bool not_killed); 565 uint purge_log_get_error_code(int res); 566 567 int vprint_msg_to_log(enum loglevel level, const char *format, va_list args); 568 void sql_print_error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2); 569 void sql_print_warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2); 570 void sql_print_information(const char *format, ...) 571 ATTRIBUTE_FORMAT(printf, 1, 2); 572 typedef void (*sql_print_message_func)(const char *format, ...) 573 ATTRIBUTE_FORMAT_FPTR(printf, 1, 2); 574 extern sql_print_message_func sql_print_message_handlers[]; 575 576 int error_log_print(enum loglevel level, const char *format, 577 va_list args); 578 579 bool slow_log_print(THD *thd, const char *query, uint query_length); 580 581 bool general_log_print(THD *thd, enum enum_server_command command, 582 const char *format,...); 583 584 bool general_log_write(THD *thd, enum enum_server_command command, 585 const char *query, uint query_length); 586 587 void sql_perror(const char *message); 588 bool flush_error_log(); 589 590 char *make_log_name(char *buff, const char *name, const char* log_ext); 591 592 /** 593 Check given log name against certain blacklisted names/extensions. 594 595 @param name Log name to check 596 @param len Length of log name 597 598 @returns true if name is valid, false otherwise. 599 */ 600 bool is_valid_log_name(const char *name, size_t len); 601 602 extern LOGGER logger; 603 604 #endif /* LOG_H */ 605