My Project
|
00001 /* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. 00002 00003 This program is free software; you can redistribute it and/or modify 00004 it under the terms of the GNU General Public License as published by 00005 the Free Software Foundation; version 2 of the License. 00006 00007 This program is distributed in the hope that it will be useful, 00008 but WITHOUT ANY WARRANTY; without even the implied warranty of 00009 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00010 GNU General Public License for more details. 00011 00012 You should have received a copy of the GNU General Public License 00013 along with this program; if not, write to the Free Software 00014 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 00015 00016 #ifndef LOG_H 00017 #define LOG_H 00018 00019 #include "unireg.h" // REQUIRED: for other includes 00020 #include "handler.h" /* my_xid */ 00021 00031 typedef struct event_coordinates 00032 { 00033 char * file_name; // binlog file name (directories stripped) 00034 my_off_t pos; // event's position in the binlog file 00035 } LOG_POS_COORD; 00036 00048 class TC_LOG 00049 { 00050 public: 00051 int using_heuristic_recover(); 00052 TC_LOG() {} 00053 virtual ~TC_LOG() {} 00054 00055 enum enum_result { 00056 RESULT_SUCCESS, 00057 RESULT_ABORTED, 00058 RESULT_INCONSISTENT 00059 }; 00060 00061 virtual int open(const char *opt_name)=0; 00062 virtual void close()=0; 00063 00077 virtual enum_result commit(THD *thd, bool all) = 0; 00078 00093 virtual int rollback(THD *thd, bool all) = 0; 00104 virtual int prepare(THD *thd, bool all) = 0; 00105 }; 00106 00107 00108 class TC_LOG_DUMMY: public TC_LOG // use it to disable the logging 00109 { 00110 public: 00111 TC_LOG_DUMMY() {} 00112 int open(const char *opt_name) { return 0; } 00113 void close() { } 00114 enum_result commit(THD *thd, bool all) { 00115 return ha_commit_low(thd, all) ? RESULT_ABORTED : RESULT_SUCCESS; 00116 } 00117 int rollback(THD *thd, bool all) { 00118 return ha_rollback_low(thd, all); 00119 } 00120 int prepare(THD *thd, bool all) { 00121 return ha_prepare_low(thd, all); 00122 } 00123 }; 00124 00125 #ifdef HAVE_MMAP 00126 class TC_LOG_MMAP: public TC_LOG 00127 { 00128 public: // only to keep Sun Forte on sol9x86 happy 00129 typedef enum { 00130 PS_POOL, // page is in pool 00131 PS_ERROR, // last sync failed 00132 PS_DIRTY // new xids added since last sync 00133 } PAGE_STATE; 00134 00135 private: 00136 typedef struct st_page { 00137 struct st_page *next; // page a linked in a fifo queue 00138 my_xid *start, *end; // usable area of a page 00139 my_xid *ptr; // next xid will be written here 00140 int size, free; // max and current number of free xid slots on the page 00141 int waiters; // number of waiters on condition 00142 PAGE_STATE state; // see above 00143 mysql_mutex_t lock; // to access page data or control structure 00144 mysql_cond_t cond; // to wait for a sync 00145 } PAGE; 00146 00147 char logname[FN_REFLEN]; 00148 File fd; 00149 my_off_t file_length; 00150 uint npages, inited; 00151 uchar *data; 00152 struct st_page *pages, *syncing, *active, *pool, *pool_last; 00153 /* 00154 note that, e.g. LOCK_active is only used to protect 00155 'active' pointer, to protect the content of the active page 00156 one has to use active->lock. 00157 Same for LOCK_pool and LOCK_sync 00158 */ 00159 mysql_mutex_t LOCK_active, LOCK_pool, LOCK_sync; 00160 mysql_cond_t COND_pool, COND_active; 00161 00162 public: 00163 TC_LOG_MMAP(): inited(0) {} 00164 int open(const char *opt_name); 00165 void close(); 00166 enum_result commit(THD *thd, bool all); 00167 int rollback(THD *thd, bool all) { return ha_rollback_low(thd, all); } 00168 int prepare(THD *thd, bool all) { return ha_prepare_low(thd, all); } 00169 int recover(); 00170 00171 private: 00172 int log_xid(THD *thd, my_xid xid); 00173 int unlog(ulong cookie, my_xid xid); 00174 void get_active_from_pool(); 00175 int sync(); 00176 int overflow(); 00177 }; 00178 #else 00179 #define TC_LOG_MMAP TC_LOG_DUMMY 00180 #endif 00181 00182 extern TC_LOG *tc_log; 00183 extern TC_LOG_MMAP tc_log_mmap; 00184 extern TC_LOG_DUMMY tc_log_dummy; 00185 00186 /* log info errors */ 00187 #define LOG_INFO_EOF -1 00188 #define LOG_INFO_IO -2 00189 #define LOG_INFO_INVALID -3 00190 #define LOG_INFO_SEEK -4 00191 #define LOG_INFO_MEM -6 00192 #define LOG_INFO_FATAL -7 00193 #define LOG_INFO_IN_USE -8 00194 #define LOG_INFO_EMFILE -9 00195 00196 00197 /* bitmap to SQL_LOG::close() */ 00198 #define LOG_CLOSE_INDEX 1 00199 #define LOG_CLOSE_TO_BE_OPENED 2 00200 #define LOG_CLOSE_STOP_EVENT 4 00201 00202 /* 00203 Maximum unique log filename extension. 00204 Note: setting to 0x7FFFFFFF due to atol windows 00205 overflow/truncate. 00206 */ 00207 #define MAX_LOG_UNIQUE_FN_EXT 0x7FFFFFFF 00208 00209 /* 00210 Number of warnings that will be printed to error log 00211 before extension number is exhausted. 00212 */ 00213 #define LOG_WARN_UNIQUE_FN_EXT_LEFT 1000 00214 00215 #ifdef HAVE_PSI_INTERFACE 00216 extern PSI_mutex_key key_LOG_INFO_lock; 00217 #endif 00218 00219 /* 00220 Note that we destroy the lock mutex in the desctructor here. 00221 This means that object instances cannot be destroyed/go out of scope, 00222 until we have reset thd->current_linfo to NULL; 00223 */ 00224 typedef struct st_log_info 00225 { 00226 char log_file_name[FN_REFLEN]; 00227 my_off_t index_file_offset, index_file_start_offset; 00228 my_off_t pos; 00229 bool fatal; // if the purge happens to give us a negative offset 00230 int entry_index; //used in purge_logs(), calculatd in find_log_pos(). 00231 mysql_mutex_t lock; 00232 st_log_info() 00233 : index_file_offset(0), index_file_start_offset(0), 00234 pos(0), fatal(0), entry_index(0) 00235 { 00236 log_file_name[0] = '\0'; 00237 mysql_mutex_init(key_LOG_INFO_lock, &lock, MY_MUTEX_INIT_FAST); 00238 } 00239 ~st_log_info() { mysql_mutex_destroy(&lock);} 00240 } LOG_INFO; 00241 00242 /* 00243 Currently we have only 3 kinds of logging functions: old-fashioned 00244 logs, stdout and csv logging routines. 00245 */ 00246 #define MAX_LOG_HANDLERS_NUM 3 00247 00248 /* log event handler flags */ 00249 #define LOG_NONE 1 00250 #define LOG_FILE 2 00251 #define LOG_TABLE 4 00252 00253 enum enum_log_type { LOG_UNKNOWN, LOG_NORMAL, LOG_BIN }; 00254 enum enum_log_state { LOG_OPENED, LOG_CLOSED, LOG_TO_BE_OPENED }; 00255 00256 /* 00257 TODO use mmap instead of IO_CACHE for binlog 00258 (mmap+fsync is two times faster than write+fsync) 00259 */ 00260 00261 class MYSQL_LOG 00262 { 00263 public: 00264 MYSQL_LOG(); 00265 void init_pthread_objects(); 00266 void cleanup(); 00267 bool open( 00268 #ifdef HAVE_PSI_INTERFACE 00269 PSI_file_key log_file_key, 00270 #endif 00271 const char *log_name, 00272 enum_log_type log_type, 00273 const char *new_name, 00274 enum cache_type io_cache_type_arg); 00275 bool init_and_set_log_file_name(const char *log_name, 00276 const char *new_name, 00277 enum_log_type log_type_arg, 00278 enum cache_type io_cache_type_arg); 00279 void init(enum_log_type log_type_arg, 00280 enum cache_type io_cache_type_arg); 00281 void close(uint exiting); 00282 inline bool is_open() { return log_state != LOG_CLOSED; } 00283 const char *generate_name(const char *log_name, const char *suffix, 00284 bool strip_ext, char *buff); 00285 int generate_new_name(char *new_name, const char *log_name); 00286 protected: 00287 /* LOCK_log is inited by init_pthread_objects() */ 00288 mysql_mutex_t LOCK_log; 00289 char *name; 00290 char log_file_name[FN_REFLEN]; 00291 char time_buff[20], db[NAME_LEN + 1]; 00292 bool write_error, inited; 00293 IO_CACHE log_file; 00294 enum_log_type log_type; 00295 volatile enum_log_state log_state; 00296 enum cache_type io_cache_type; 00297 friend class Log_event; 00298 #ifdef HAVE_PSI_INTERFACE 00299 00300 PSI_file_key m_log_file_key; 00302 PSI_mutex_key m_key_LOCK_log; 00303 #endif 00304 }; 00305 00306 00307 enum enum_general_log_table_field 00308 { 00309 GLT_FIELD_EVENT_TIME = 0, 00310 GLT_FIELD_USER_HOST, 00311 GLT_FIELD_THREAD_ID, 00312 GLT_FIELD_SERVER_ID, 00313 GLT_FIELD_COMMAND_TYPE, 00314 GLT_FIELD_ARGUMENT, 00315 GLT_FIELD_COUNT 00316 }; 00317 00318 00319 enum enum_slow_query_log_table_field 00320 { 00321 SQLT_FIELD_START_TIME = 0, 00322 SQLT_FIELD_USER_HOST, 00323 SQLT_FIELD_QUERY_TIME, 00324 SQLT_FIELD_LOCK_TIME, 00325 SQLT_FIELD_ROWS_SENT, 00326 SQLT_FIELD_ROWS_EXAMINED, 00327 SQLT_FIELD_DATABASE, 00328 SQLT_FIELD_LAST_INSERT_ID, 00329 SQLT_FIELD_INSERT_ID, 00330 SQLT_FIELD_SERVER_ID, 00331 SQLT_FIELD_SQL_TEXT, 00332 SQLT_FIELD_THREAD_ID, 00333 SQLT_FIELD_COUNT 00334 }; 00335 00336 00337 class MYSQL_QUERY_LOG: public MYSQL_LOG 00338 { 00339 public: 00340 MYSQL_QUERY_LOG() : last_time(0) {} 00341 void reopen_file(); 00342 bool write(time_t event_time, const char *user_host, 00343 uint user_host_len, my_thread_id thread_id, 00344 const char *command_type, uint command_type_len, 00345 const char *sql_text, uint sql_text_len); 00346 bool write(THD *thd, time_t current_time, time_t query_start_arg, 00347 const char *user_host, uint user_host_len, 00348 ulonglong query_utime, ulonglong lock_utime, bool is_command, 00349 const char *sql_text, uint sql_text_len); 00350 bool open_slow_log(const char *log_name) 00351 { 00352 char buf[FN_REFLEN]; 00353 return open( 00354 #ifdef HAVE_PSI_INTERFACE 00355 key_file_slow_log, 00356 #endif 00357 generate_name(log_name, "-slow.log", 0, buf), 00358 LOG_NORMAL, 0, WRITE_CACHE); 00359 } 00360 bool open_query_log(const char *log_name) 00361 { 00362 char buf[FN_REFLEN]; 00363 return open( 00364 #ifdef HAVE_PSI_INTERFACE 00365 key_file_query_log, 00366 #endif 00367 generate_name(log_name, ".log", 0, buf), 00368 LOG_NORMAL, 0, WRITE_CACHE); 00369 } 00370 00371 private: 00372 time_t last_time; 00373 }; 00374 00375 class Log_event_handler 00376 { 00377 public: 00378 Log_event_handler() {} 00379 virtual bool init()= 0; 00380 virtual void cleanup()= 0; 00381 00382 virtual bool log_slow(THD *thd, time_t current_time, 00383 time_t query_start_arg, const char *user_host, 00384 uint user_host_len, ulonglong query_utime, 00385 ulonglong lock_utime, bool is_command, 00386 const char *sql_text, uint sql_text_len)= 0; 00387 virtual bool log_error(enum loglevel level, const char *format, 00388 va_list args)= 0; 00389 virtual bool log_general(THD *thd, time_t event_time, const char *user_host, 00390 uint user_host_len, my_thread_id thread_id, 00391 const char *command_type, uint command_type_len, 00392 const char *sql_text, uint sql_text_len, 00393 const CHARSET_INFO *client_cs)= 0; 00394 virtual ~Log_event_handler() {} 00395 }; 00396 00397 00398 int check_if_log_table(size_t db_len, const char *db, size_t table_name_len, 00399 const char *table_name, bool check_if_opened); 00400 00401 class Log_to_csv_event_handler: public Log_event_handler 00402 { 00403 public: 00404 Log_to_csv_event_handler(); 00405 ~Log_to_csv_event_handler(); 00406 virtual bool init(); 00407 virtual void cleanup(); 00408 00409 virtual bool log_slow(THD *thd, time_t current_time, 00410 time_t query_start_arg, const char *user_host, 00411 uint user_host_len, ulonglong query_utime, 00412 ulonglong lock_utime, bool is_command, 00413 const char *sql_text, uint sql_text_len); 00414 virtual bool log_error(enum loglevel level, const char *format, 00415 va_list args); 00416 virtual bool log_general(THD *thd, time_t event_time, const char *user_host, 00417 uint user_host_len, my_thread_id thread_id, 00418 const char *command_type, uint command_type_len, 00419 const char *sql_text, uint sql_text_len, 00420 const CHARSET_INFO *client_cs); 00421 00422 int activate_log(THD *thd, uint log_type); 00423 }; 00424 00425 00426 /* type of the log table */ 00427 #define QUERY_LOG_SLOW 1 00428 #define QUERY_LOG_GENERAL 2 00429 00430 class Log_to_file_event_handler: public Log_event_handler 00431 { 00432 MYSQL_QUERY_LOG mysql_log; 00433 MYSQL_QUERY_LOG mysql_slow_log; 00434 bool is_initialized; 00435 public: 00436 Log_to_file_event_handler(): is_initialized(FALSE) 00437 {} 00438 virtual bool init(); 00439 virtual void cleanup(); 00440 00441 virtual bool log_slow(THD *thd, time_t current_time, 00442 time_t query_start_arg, const char *user_host, 00443 uint user_host_len, ulonglong query_utime, 00444 ulonglong lock_utime, bool is_command, 00445 const char *sql_text, uint sql_text_len); 00446 virtual bool log_error(enum loglevel level, const char *format, 00447 va_list args); 00448 virtual bool log_general(THD *thd, time_t event_time, const char *user_host, 00449 uint user_host_len, my_thread_id thread_id, 00450 const char *command_type, uint command_type_len, 00451 const char *sql_text, uint sql_text_len, 00452 const CHARSET_INFO *client_cs); 00453 void flush(); 00454 void init_pthread_objects(); 00455 MYSQL_QUERY_LOG *get_mysql_slow_log() { return &mysql_slow_log; } 00456 MYSQL_QUERY_LOG *get_mysql_log() { return &mysql_log; } 00457 }; 00458 00459 00460 /* Class which manages slow, general and error log event handlers */ 00461 class LOGGER 00462 { 00463 mysql_rwlock_t LOCK_logger; 00464 /* flag to check whether logger mutex is initialized */ 00465 uint inited; 00466 00467 /* available log handlers */ 00468 Log_to_csv_event_handler *table_log_handler; 00469 Log_to_file_event_handler *file_log_handler; 00470 00471 /* NULL-terminated arrays of log handlers */ 00472 Log_event_handler *error_log_handler_list[MAX_LOG_HANDLERS_NUM + 1]; 00473 Log_event_handler *slow_log_handler_list[MAX_LOG_HANDLERS_NUM + 1]; 00474 Log_event_handler *general_log_handler_list[MAX_LOG_HANDLERS_NUM + 1]; 00475 00476 public: 00477 00478 bool is_log_tables_initialized; 00479 00480 LOGGER() : inited(0), table_log_handler(NULL), 00481 file_log_handler(NULL), is_log_tables_initialized(FALSE) 00482 {} 00483 void lock_shared() { mysql_rwlock_rdlock(&LOCK_logger); } 00484 void lock_exclusive() { mysql_rwlock_wrlock(&LOCK_logger); } 00485 void unlock() { mysql_rwlock_unlock(&LOCK_logger); } 00486 bool is_log_table_enabled(uint log_table_type); 00487 bool log_command(THD *thd, enum enum_server_command command, 00488 const char *query_str, size_t query_length); 00489 00490 /* 00491 We want to initialize all log mutexes as soon as possible, 00492 but we cannot do it in constructor, as safe_mutex relies on 00493 initialization, performed by MY_INIT(). This why this is done in 00494 this function. 00495 */ 00496 void init_base(); 00497 void init_log_tables(); 00498 bool flush_logs(THD *thd); 00499 bool flush_slow_log(); 00500 bool flush_general_log(); 00501 /* Perform basic logger cleanup. this will leave e.g. error log open. */ 00502 void cleanup_base(); 00503 /* Free memory. Nothing could be logged after this function is called */ 00504 void cleanup_end(); 00505 bool error_log_print(enum loglevel level, const char *format, 00506 va_list args); 00507 bool slow_log_print(THD *thd, const char *query, uint query_length); 00508 bool general_log_print(THD *thd,enum enum_server_command command, 00509 const char *format, va_list args); 00510 bool general_log_write(THD *thd, enum enum_server_command command, 00511 const char *query, uint query_length); 00512 00513 /* we use this function to setup all enabled log event handlers */ 00514 int set_handlers(uint error_log_printer, 00515 uint slow_log_printer, 00516 uint general_log_printer); 00517 void init_error_log(uint error_log_printer); 00518 void init_slow_log(uint slow_log_printer); 00519 void init_general_log(uint general_log_printer); 00520 void deactivate_log_handler(THD* thd, uint log_type); 00521 bool activate_log_handler(THD* thd, uint log_type); 00522 MYSQL_QUERY_LOG *get_slow_log_file_handler() const 00523 { 00524 if (file_log_handler) 00525 return file_log_handler->get_mysql_slow_log(); 00526 return NULL; 00527 } 00528 MYSQL_QUERY_LOG *get_log_file_handler() const 00529 { 00530 if (file_log_handler) 00531 return file_log_handler->get_mysql_log(); 00532 return NULL; 00533 } 00534 }; 00535 00536 enum enum_binlog_row_image { 00538 BINLOG_ROW_IMAGE_MINIMAL= 0, 00540 BINLOG_ROW_IMAGE_NOBLOB= 1, 00542 BINLOG_ROW_IMAGE_FULL= 2 00543 }; 00544 00545 enum enum_binlog_format { 00546 BINLOG_FORMAT_MIXED= 0, 00547 BINLOG_FORMAT_STMT= 1, 00548 BINLOG_FORMAT_ROW= 2, 00549 BINLOG_FORMAT_UNSPEC=3 00550 }; 00551 00552 int query_error_code(THD *thd, bool not_killed); 00553 uint purge_log_get_error_code(int res); 00554 00555 int vprint_msg_to_log(enum loglevel level, const char *format, va_list args); 00556 void sql_print_error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2); 00557 void sql_print_warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2); 00558 void sql_print_information(const char *format, ...) 00559 ATTRIBUTE_FORMAT(printf, 1, 2); 00560 typedef void (*sql_print_message_func)(const char *format, ...) 00561 ATTRIBUTE_FORMAT_FPTR(printf, 1, 2); 00562 extern sql_print_message_func sql_print_message_handlers[]; 00563 00564 int error_log_print(enum loglevel level, const char *format, 00565 va_list args); 00566 00567 bool slow_log_print(THD *thd, const char *query, uint query_length); 00568 00569 bool general_log_print(THD *thd, enum enum_server_command command, 00570 const char *format,...); 00571 00572 bool general_log_write(THD *thd, enum enum_server_command command, 00573 const char *query, uint query_length); 00574 00575 void sql_perror(const char *message); 00576 bool flush_error_log(); 00577 00578 char *make_log_name(char *buff, const char *name, const char* log_ext); 00579 00580 extern LOGGER logger; 00581 00582 #endif /* LOG_H */